Hi,
I am curious how to make generic method which will return generic type.
Something like:
class Test {
T Get<T>() {
if(T is int) {
return 1; //return int
}
else if(T is string) {
return "11"; //return string
}
else if(T is DateTime) {
return DateTime.Now; //return DateTime
}
}
void MyTest() {
int i = Get<int>();
string s = Get<string>();
DateTime d = Get<DateTime>();
}
}
Thanks,
Zdenko
Marc Gravell - 04 Mar 2008 12:49 GMT
You have to always think in terms of T... default(T) would be the most
obvious, which is 0/false for value-types [i.e. blit-zero], and null for
reference-types (and Nullable<T>) -
i.e.
T Get<T>() {
return default(T);
}
Other than that, it gets complicated... many things are possible, but we'd
need a bit more detail on what you want to do. Casting is possible, but
messy, and often involves going to "object" in the middle.
Finally, your method must cover every logical path, even if the catch-all
step is simply throw new NotSupportedException()...
Marc
Jon Skeet [C# MVP] - 04 Mar 2008 12:59 GMT
> I am curious how to make generic method which will return generic type.
> Something like:
[quoted text clipped - 18 lines]
> }
> }
Well, you can get it to work, but it's ugly:
using System;
class Test
{
static T Get<T>()
{
if(typeof(T)==typeof(int))
{
return (T)(object)1; //return int
}
if(typeof(T)==typeof(string))
{
return (T)(object)"11"; //return string
}
if(typeof(T)==typeof(DateTime))
{
return (T)(object)DateTime.Now; //return DateTime
}
return default(T);
}
static void Main()
{
int i = Get<int>();
Console.WriteLine(i);
string s = Get<string>();
Console.WriteLine(s);
DateTime d = Get<DateTime>();
Console.WriteLine(d);
}
}
This is an odd use of generics in the first place though. Could you
give a bit more explanation of why you want to do this? There may be a
better way.

Signature
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
World class .NET training in the UK: http://iterativetraining.co.uk
Rene - 04 Mar 2008 15:57 GMT
Hi Jon,
Interesting, I guess I never really paid any attention to this so I decided
to do a little experiment like the one below:
T Get<T>()
{
return (T)( new Exception() );
}
The example above won't run and gives me a casting compile error.
The interesting thing I see here is that I don't get this error when you try
to cast an *object* to <T> (like in your example).
I find this interesting because the compiler seems to give the code the
benefit of the doubt only when casting from *object* to <T> although the
cast may fail.
However, the compiler will not give the "Exception" object the benefit of
the doubt although it is possible that you could potentially cast the
"Exception" object to "ArgumentException", "InvalidOperationException" or
even "Object" and still be a valid cast.
This looks to me like the compiler has double standards :)
>> I am curious how to make generic method which will return generic type.
>> Something like:
[quoted text clipped - 56 lines]
> give a bit more explanation of why you want to do this? There may be a
> better way.
Marc Gravell - 04 Mar 2008 16:07 GMT
The bahaviour is the same as for non-generic code:
string x = "abc";
int foo = (int)(object)x; // compiles but fails
int bar = (int)x; // doesn't compile
Jon Skeet [C# MVP] - 04 Mar 2008 16:08 GMT
> Interesting, I guess I never really paid any attention to this so I decided
> to do a little experiment like the one below:
[quoted text clipped - 19 lines]
>
> This looks to me like the compiler has double standards :)
Well, it's following the spec - in this case section 6.2.6 (of the
unified C# 3 spec).
It's allowing a cast from "the effective base class C of T to T". The
effective base class of an unconstrained type parameter (like T in your
case) is object.

Signature
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
World class .NET training in the UK: http://iterativetraining.co.uk
Rene - 04 Mar 2008 21:30 GMT
> Well, it's following the spec - in this case section 6.2.6 (of the
> unified C# 3 spec).
>
> It's allowing a cast from "the effective base class C of T to T". The
> effective base class of an unconstrained type parameter (like T in your
> case) is object.
I will never have the brains to tackle the spec document however I continue
to experiment and this compiles:
static T Get<T>() where T : Exception
{
return (T)( (Exception) new object() );
}
So my guess is that "the effective base class" is now the "Exception" class
since the <T> is constrained by "Exception".
Anyway, I am fine with the way things work, I was just wondering what dark
secrets lay underneath the compiler to make decisions such as this one, I
wonder if you would need to cast to object if you where doing this directly
in IL.
Oh well, no biggie :)
Zdenko - 05 Mar 2008 10:05 GMT
I would like to parse byte array whic I get from other non .NET application.
Byte array is serialized object. To access specific property I am using:
object o = msg.GetProperty(idx); //where idx is index of property
I would like to make strongly type geters.
I know that property with index 1 is zero and I can write code:
int i = msg.GetInt(1);
Using this approach I would have getters for every type of return value. I
would like to use generic and create single Get method which will handle
parsing of specific field and create proper return value:
int i = msg.Get<int>(3);
string s = msg.get<string>(7);
etc... (for every supported type) or InvalidCastException if field is not of
Generic type T.
Zdenko
> Hi,
>
[quoted text clipped - 23 lines]
> Thanks,
> Zdenko
Jon Skeet [C# MVP] - 05 Mar 2008 12:59 GMT
> I would like to parse byte array whic I get from other non .NET application.
> Byte array is serialized object. To access specific property I am using:
[quoted text clipped - 10 lines]
> etc... (for every supported type) or InvalidCastException if field is not of
> Generic type T.
The advantages of the GetInt32, GetDateTime etc approach are:
o It avoids the horrible casting within the method
o It makes it clear which types are supported
o The attempt to use an unsupported type fails to compile time
rather than execution time.

Signature
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
World class .NET training in the UK: http://iterativetraining.co.uk
Zdenko - 05 Mar 2008 14:53 GMT
> o It avoids the horrible casting within the method
> o It makes it clear which types are supported
> o The attempt to use an unsupported type fails to compile time rather than
> execution time.
Every argument is right.
As I said in my first mail: "Out of curiosity".
I do not know how to return value of type T without compiler error.
I would like to know how could I achieve this.
Zdenko
>> I would like to parse byte array whic I get from other non .NET
>> application.
[quoted text clipped - 20 lines]
> o The attempt to use an unsupported type fails to compile time
> rather than execution time.
Jon Skeet [C# MVP] - 05 Mar 2008 15:31 GMT
> > o It avoids the horrible casting within the method
> > o It makes it clear which types are supported
[quoted text clipped - 6 lines]
> I do not know how to return value of type T without compiler error.
> I would like to know how could I achieve this.
See my first post to this thread.

Signature
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
World class .NET training in the UK: http://iterativetraining.co.uk
Zdenko - 06 Mar 2008 12:23 GMT
I have seen it. I was thinking that someone can come with different
approach.
At least it works.
Thanks
Zdenko
>> > o It avoids the horrible casting within the method
>> > o It makes it clear which types are supported
[quoted text clipped - 9 lines]
>
> See my first post to this thread.
Anjum Rizwi - 27 Oct 2008 07:41 GMT
protected T ExecuteScalar<T>(DbCommand cmd)
{
object obj;
try
{
obj = db.ExecuteScalar(cmd);
return (T) obj;
}
catch
{
throw;
}
}
It gives me casting error
return (T) obj; //cast error
I call like this
return base.ExecuteScalar<bool>(dbCommand);// It returns 0
Alex Meleta - 27 Oct 2008 08:23 GMT
Hi Anjum,
What is the type of T and obj at the moment of execution. It's hard to convert
to bool something other than bool in the case of direct casting
Regards, Alex Meleta
[TechBlog] http://devkids.blogspot.com