473,385 Members | 1,602 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

C# typeof() and Generics

Let's say that you have:

class A
{
T DoSomething<T>() where T : class, new()
{
T ThisObj = new T();
// Do something usefull...
return ThisObj;
}

void StartHere(Type type)
{
// And here is the problem
DoSomething<type>();
}
}

Any Ideas on how to call a generic function like 'DoSomething' when the calling function got the type as a parameter, not as a type parameter?

Jorge Varas

Oct 26 '06 #1
12 14872
Let's say that you have:
>
class A
{
T DoSomething<T>() where T : class, new()
{
T ThisObj = new T();
// Do something usefull...
return ThisObj;
}
void StartHere(Type type)
{
// And here is the problem
DoSomething<type>();
}
}
Any Ideas on how to call a generic function like 'DoSomething' when
the calling function got the type as a parameter, not as a type
parameter?
Unfortunately, this can't be done (and I don't see how "typeof" is used here).
The closest that you could get is to make the StartHere method generic like
this:

class A
{
T DoSomething<T>() where T : class, new()
{
T ThisObj = new T();
// Do something usefull...
return ThisObj;
}

void StartHere<T>()
{
// And here is the problem
T myValue = DoSomething<T>();
}
}

Best Regards,
Dustin Campbell
Developer Express Inc.
Oct 26 '06 #2


"Dustin Campbell" <du*****@no-spam-pleasedevexpress.comwrote in message news:c1**************************@news.microsoft.c om...

Unfortunately, this can't be done (and I don't see how "typeof" is used here).
About the usage of typeof, here is an example of what I mean (this works):

class Program
{
static void Main(string[] args)
{
Test test = new Test();
test.CallMe();
}
}

class Test
{
public void CallMe()
{
this.DoSomething<Test>();
}
public void DoSomething<T>() where T : class, new()
{
Console.WriteLine(typeof(T).FullName);
}
}

Here I can use typeof to get the type of a Type Parameter. I was hoping that there was a way (maybe using typeof) to solve the first problem.
The closest that you could get is to make the StartHere method generic like
this:

class A
{
T DoSomething<T>() where T : class, new()
{
T ThisObj = new T();
// Do something usefull...
return ThisObj;
}

void StartHere<T>()
{
// And here is the problem
T myValue = DoSomething<T>();
}
}
I know, but in my case I am retrieving the type of a property using reflection, and that is the type that I need to pass to the generic DoSomething, so no point to make the initial call generic. The other option is to make a non-generic version of DoSomething and just eat the performance impact of the boxing.

Jorge Varas

Oct 26 '06 #3
You can, but you need to use reflection, which is (relatively) slow; in
particular, you would obtain the MethodInfo for the method ("GetMethod"),
and then call MakeGenericMethod(), which accepts the Type instances.

You would then .Invoke the returned method info.

Marc
Oct 26 '06 #4
I know, but in my case I am retrieving the type of a property using
reflection, and that is the type that I need to pass to the generic
DoSomething, so no point to make the initial call generic. The other
option is to make a non-generic version of DoSomething and just eat
the performance impact of the boxing.
If you're already using reflection, boxing should be the least of your performance
worries. :-) Second of all, the generic constraints that you've applied to
DoSomething<Tensure that their won't be any boxing operations because only
reference types can be used with it. And finally, if you're using reflection,
you *could* use reflection to dynamically set the generic argument to your
method and invoke it like this:

using System;
using System.Reflection;

namespace ConsoleApp
{
class Program
{
class A
{
T DoSomething<T>() where T: class, new()
{
T ThisObj = new T();
// Do something usefull...
return ThisObj;
}

public void StartHere(Type type)
{
MethodInfo method = this.GetType().GetMethod("DoSomething", BindingFlags.NonPublic
| BindingFlags.Instance);
MethodInfo closedMethod = method.MakeGenericMethod(type);

object o = closedMethod.Invoke(this, null);
}
}

static void Main(string[] args)
{
new A().StartHere(typeof(A));
}
}
}

Of course, if the "class" generic constraint isn't used, there would potentially
be boxing because the Invoke() method returns a System.Object.

Best Regards,
Dustin Campbell
Developer Express Inc.
Oct 26 '06 #5
Cool!

I was not aware of MakeGenericMethodt. I'll give it a try.

{ ... things I have to do because C# has a very limited support for AOP }
"Marc Gravell" <ma**********@gmail.comwrote in message
news:Oq****************@TK2MSFTNGP03.phx.gbl...
You can, but you need to use reflection, which is (relatively) slow; in
particular, you would obtain the MethodInfo for the method ("GetMethod"),
and then call MakeGenericMethod(), which accepts the Type instances.

You would then .Invoke the returned method info.

Marc

Oct 26 '06 #6
I am caching the reflection information, but is still in reflected types
format (propertyInfo and so) so my performace is prety good (or my pc is
pretty fast, whichever is working) because I cache the information on
program start up, rather than at every call.

The boxing operation that I was worry about was going to be if I needed to
make a non-generic version (thus object type based) version of the same
function.

As I pointed out to mark, I didn't know about the "MakeGenericMethod" usage,
so I'll give it a try.

"Dustin Campbell" <du*****@no-spam-pleasedevexpress.comwrote in message
news:c1**************************@news.microsoft.c om...
>I know, but in my case I am retrieving the type of a property using
reflection, and that is the type that I need to pass to the generic
DoSomething, so no point to make the initial call generic. The other
option is to make a non-generic version of DoSomething and just eat
the performance impact of the boxing.

If you're already using reflection, boxing should be the least of your
performance worries. :-) Second of all, the generic constraints that
you've applied to DoSomething<Tensure that their won't be any boxing
operations because only reference types can be used with it. And finally,
if you're using reflection, you *could* use reflection to dynamically set
the generic argument to your method and invoke it like this:

using System;
using System.Reflection;

namespace ConsoleApp
{
class Program
{
class A
{
T DoSomething<T>() where T: class, new()
{
T ThisObj = new T();
// Do something usefull...
return ThisObj;
}

public void StartHere(Type type)
{
MethodInfo method = this.GetType().GetMethod("DoSomething",
BindingFlags.NonPublic | BindingFlags.Instance);
MethodInfo closedMethod = method.MakeGenericMethod(type);

object o = closedMethod.Invoke(this, null);
}
}

static void Main(string[] args)
{
new A().StartHere(typeof(A));
}
}
}

Of course, if the "class" generic constraint isn't used, there would
potentially be boxing because the Invoke() method returns a System.Object.

Best Regards,
Dustin Campbell
Developer Express Inc.


Oct 26 '06 #7
The boxing operation that I was worry about was going to be if I
needed to make a non-generic version (thus object type based) version
of the same function.
Sure, but I assumed that you weren't going to be using value types since
you had declared the "class" generic constraint. If you have an object-type
parameter but never use a value type with it, you won't have boxing.

Best Regards,
Dustin Campbell
Developer Express Inc.
Oct 26 '06 #8
Then there is something more I need to learn... What I understand from what
you are saying is that there never is boxing between reference types? only
for value types that are used as objects?

Thus this piece of code does not do any boxing on the third line?

StringBuilder sb = new StringBuilder();
sb.Add("Whatever");
object o = (object)sb;
Console.WriteLine(o.ToString());

Jorge Varas

"Dustin Campbell" <du*****@no-spam-pleasedevexpress.comwrote in message
news:c1**************************@news.microsoft.c om...
>The boxing operation that I was worry about was going to be if I
needed to make a non-generic version (thus object type based) version
of the same function.

Sure, but I assumed that you weren't going to be using value types since
you had declared the "class" generic constraint. If you have an
object-type parameter but never use a value type with it, you won't have
boxing.

Best Regards,
Dustin Campbell
Developer Express Inc.


Oct 26 '06 #9
Then there is something more I need to learn... What I understand from
what you are saying is that there never is boxing between reference
types? only for value types that are used as objects?

Thus this piece of code does not do any boxing on the third line?

StringBuilder sb = new StringBuilder();
sb.Add("Whatever");
object o = (object)sb;
Console.WriteLine(o.ToString());
Correct.

This code:

private void Test()
{
StringBuilder sb = new StringBuilder();
sb.Append("Whatever");
object o = (object)sb;
Console.WriteLine(o.ToString());
}

Compiles to this:

..method private hidebysig instance void Test() cil managed
{
.maxstack 2
.locals init (
[0] [mscorlib]System.Text.StringBuilder sb,
[1] object o)
L_0000: nop
L_0001: newobj instance void [mscorlib]System.Text.StringBuilder::.ctor()
L_0006: stloc.0
L_0007: ldloc.0
L_0008: ldstr "Whatever"
L_000d: callvirt instance [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
L_0012: pop
L_0013: ldloc.0
L_0014: stloc.1
L_0015: ldloc.1
L_0016: callvirt instance string object::ToString()
L_001b: call void [mscorlib]System.Console::WriteLine(string)
L_0020: nop
L_0021: ret
}

This code:

private void Test()
{
int i = 1;
object o = (object)i;
Console.WriteLine(o.ToString());
}

Compiles to this:

..method private hidebysig instance void Test() cil managed
{
.maxstack 1
.locals init (
[0] int32 i,
[1] object o)
L_0000: nop
L_0001: ldc.i4.1
L_0002: stloc.0
L_0003: ldloc.0
L_0004: box int32
L_0009: stloc.1
L_000a: ldloc.1
L_000b: callvirt instance string object::ToString()
L_0010: call void [mscorlib]System.Console::WriteLine(string)
L_0015: nop
L_0016: ret
}

Notice the boxing operation in the second method when the Int32 is cast to
an object.


Best Regards,
Dustin Campbell
Developer Express Inc.

Oct 26 '06 #10
Thanks for the explanation and your time.

One of these days I need to learn CLI, Emit() and all that area of .Net.
(Can you suggest a good starting point?)

All the hoops and loops that I am doing is to be able to intercept access to
properties of a class. I know that this can be done by inhert the class from
ContextBound and intercepting the call sink. But .Net supports only single
inheritance, which prevents me from using inheritance in my business model
if I also have to inherit from ContextBound.

I know about this project:

http://wwwse.fhs-hagenberg.ac.at/se/...h/aop_net.html

But I have not see a single example of it. Do you know more references?

Jorge Varas

"Dustin Campbell" <du*****@no-spam-pleasedevexpress.comwrote in message
news:c1**************************@news.microsoft.c om...
>Then there is something more I need to learn... What I understand from
what you are saying is that there never is boxing between reference
types? only for value types that are used as objects?

Thus this piece of code does not do any boxing on the third line?

StringBuilder sb = new StringBuilder();
sb.Add("Whatever");
object o = (object)sb;
Console.WriteLine(o.ToString());

Correct.

This code:

private void Test()
{
StringBuilder sb = new StringBuilder();
sb.Append("Whatever");
object o = (object)sb;
Console.WriteLine(o.ToString());
}

Compiles to this:

.method private hidebysig instance void Test() cil managed
{
.maxstack 2
.locals init (
[0] [mscorlib]System.Text.StringBuilder sb,
[1] object o)
L_0000: nop L_0001: newobj instance void
[mscorlib]System.Text.StringBuilder::.ctor()
L_0006: stloc.0 L_0007: ldloc.0 L_0008: ldstr "Whatever"
L_000d: callvirt instance [mscorlib]System.Text.StringBuilder
[mscorlib]System.Text.StringBuilder::Append(string)
L_0012: pop L_0013: ldloc.0 L_0014: stloc.1 L_0015: ldloc.1 L_0016:
callvirt instance string object::ToString()
L_001b: call void [mscorlib]System.Console::WriteLine(string)
L_0020: nop L_0021: ret }

This code:

private void Test()
{
int i = 1;
object o = (object)i;
Console.WriteLine(o.ToString());
}

Compiles to this:

.method private hidebysig instance void Test() cil managed
{
.maxstack 1
.locals init (
[0] int32 i,
[1] object o)
L_0000: nop L_0001: ldc.i4.1 L_0002: stloc.0 L_0003: ldloc.0 L_0004:
box int32
L_0009: stloc.1 L_000a: ldloc.1 L_000b: callvirt instance string
object::ToString()
L_0010: call void [mscorlib]System.Console::WriteLine(string)
L_0015: nop L_0016: ret }

Notice the boxing operation in the second method when the Int32 is cast to
an object.


Best Regards,
Dustin Campbell
Developer Express Inc.

Oct 26 '06 #11
It isn't just obtaining the PropertyInfo, MethodInfo (etc) instances that is
slow; it is also (comparatively) slow when *using* them - e.g. GetValue /
SetValue for properties, Invoke for members... all slower, as it has to do a
lot to enusure you aren't attempting bad things. Quite painful if you are in
a tight loop.

Sometimes reflection is necessary; but in a lot of cases it is [ab]used
because it gets the programmer out of a hole. Often, suitable interface
declarations can be used to make this a *lot* quicker. Alternatively,
(typed) delegates can sometimes be suitable (especially in 2.0 where they
are quicker).

I don't know enough about your other code to know if it is being used wisely
(not do I really want to know ;-p) - I'm just making a generalisation.
Saying that; if you're code works, it may be inadvisable to hack it too
much... but worth considering for the future.

Marc
Oct 26 '06 #12
I am not in such tight loop. It is not a high performance app where every
milli-second count. So reflection performance is ok.
I am tinkering with my own code, not someone elses, so I can hack it as much
as I want. I don;t want to tie to specific interfaces or inherit from
certain class. I just want to decorate with attributes and the code being
intercepted, but looks like there is no way out of using reflection, or
inherit from ContextBoundObject.

The only project that did something in this style was:
http://wwwse.fhs-hagenberg.ac.at/se/...h/aop_net.html

But the guy will not give a sample.

Is there any recomended place to start studing the Emit codes and the
CLI/CLR?

Jorge Varas
"Marc Gravell" <ma**********@gmail.comwrote in message
news:ub****************@TK2MSFTNGP05.phx.gbl...
It isn't just obtaining the PropertyInfo, MethodInfo (etc) instances that
is slow; it is also (comparatively) slow when *using* them - e.g. GetValue
/ SetValue for properties, Invoke for members... all slower, as it has to
do a lot to enusure you aren't attempting bad things. Quite painful if you
are in a tight loop.

Sometimes reflection is necessary; but in a lot of cases it is [ab]used
because it gets the programmer out of a hole. Often, suitable interface
declarations can be used to make this a *lot* quicker. Alternatively,
(typed) delegates can sometimes be suitable (especially in 2.0 where they
are quicker).

I don't know enough about your other code to know if it is being used
wisely (not do I really want to know ;-p) - I'm just making a
generalisation.
Saying that; if you're code works, it may be inadvisable to hack it too
much... but worth considering for the future.

Marc

Oct 26 '06 #13

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

27
by: Bernardo Heynemann | last post by:
How can I use Generics? How can I use C# 2.0? I already have VS.NET 2003 Enterprise Edition and still can´t use generics... I´m trying to make a generic collection myCollection<vartype> and...
23
by: Luc Vaillant | last post by:
I need to initialise a typed parameter depending of its type in a generic class. I have tried to use the C++ template form as follow, but it doesn't work. It seems to be a limitation of generics...
12
by: Michael S | last post by:
Why do people spend so much time writing complex generic types? for fun? to learn? for use? I think of generics like I do about operator overloading. Great to have as a language-feature, as...
9
by: sloan | last post by:
I'm not the sharpest knife in the drawer, but not a dummy either. I'm looking for a good book which goes over Generics in great detail. and to have as a reference book on my shelf. Personal...
1
by: Vladimir Shiryaev | last post by:
Hello! Exception handling in generics seems to be a bit inconsistent to me. Imagine, I have "MyOwnException" class derived from "ApplicationException". I also have two classes...
11
by: Einar Værnes | last post by:
Hi. I am trying to programatically decide which type a new object should have, but the typeof-function is apparently not the answer, as the following code will not compile. class...
2
by: =?Utf-8?B?SmVzcGVyLCBEZW5tYXJr?= | last post by:
Hi I need to parse strings to enumerated types for several different enumerated types. Im doing this for each of them, bu I wonder if there is a way to write a generic method that also takes...
13
by: rkausch | last post by:
Hello everyone, I'm writing because I'm frustrated with the implementation of C#'s generics, and need a workaround. I come from a Java background, and am currently writing a portion of an...
3
by: Stefan Hoffmann | last post by:
hi @all, I have the following interface declaration: public interface IBaseDao<Twhere T : BasePOJO { List<TFindAll(Type entityClass); } The parameter entityClass should be typeof(T).
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.