By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,723 Members | 1,407 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,723 IT Pros & Developers. It's quick & easy.

Generic Interfaces and casting from object at runtime problem

P: n/a
Let's say that I would like a generic type that supports Min/Max
properties and can be double or integer or even datetime if need be,
something flexible.

So I go about creating the following generic interface :

*note : in reality I implement the IComparable and IEquatable generic
interfaces and associated overriden methods, but I've cut everything
down to the bare minimum for this example.

public interface IMinMax<T>
{
T Min{get;}
T Max{get;}
}

and the following generic struct :

public struct MinMax<T: IMinMax<T>
{
private readonly T min;
private readonly T max;

public T Min
{
get
{
return min;
}
}

public T Max
{
get
{
return max;
}
}

public MinMax(T min, T max)
{
this.min = min;
this.max = max;
}

}
Now here's some code to use it :

IMinMax<intintMinMax = new MinMax<int>(0, 100); // percentage range
IMinMax<ddateMinMax = new MinMax<DateTime>(new DateTime(1973, 10,
4), DateTime.Now); // date range
Okay, so here's the problem... what if I have the following
procedure :

public void DoSomething(object o)
{
IMinMax<mm = (IMinMax<>) o; // this doesn't work

// do something with mm.Min and mm.Max here
}

and I want to call the procedure as follows :

DoSomething(intMinMax);
DoSomething(dateMinMax);
How do we go about doing something with Min and Max? Obviously there's
a lot of meat missing in the code and I simplified it quite
unrealistically for the purpose of this newsgroup so please no
questions as to why I would want to do it... this comes up all the
time in one form or another.

I guess the real question is... once you've cast a generic interface
to an object, how do you go about extracting its information at run-
time? In my case I happen to know the type at runtime but the
following modified method still doesn't work :

public void DoSomething(Type t, object o)
{
IMinMax<tmm = (IMinMax<t>) o; // still doesn't work

// do something with mm.Min and mm.Max here
}
Regards!

Anthony

Jul 17 '07 #1
Share this Question
Share on Google+
15 Replies


P: n/a
Your struct (or value type) is boxed and the type information seems lost
when it is converted to object..
You can try C++/CLI, which retains type information when you box a value
type.
Reference
C++: The Most Powerful Language for .NET Framework Programming by Kenny
Kerr, MSDN
--
Sheng Jiang
Microsoft MVP in VC++
"Anthony Paul" <an**********@gmail.comwrote in message
news:11**********************@o11g2000prd.googlegr oups.com...
Let's say that I would like a generic type that supports Min/Max
properties and can be double or integer or even datetime if need be,
something flexible.

So I go about creating the following generic interface :

*note : in reality I implement the IComparable and IEquatable generic
interfaces and associated overriden methods, but I've cut everything
down to the bare minimum for this example.

public interface IMinMax<T>
{
T Min{get;}
T Max{get;}
}

and the following generic struct :

public struct MinMax<T: IMinMax<T>
{
private readonly T min;
private readonly T max;

public T Min
{
get
{
return min;
}
}

public T Max
{
get
{
return max;
}
}

public MinMax(T min, T max)
{
this.min = min;
this.max = max;
}

}
Now here's some code to use it :

IMinMax<intintMinMax = new MinMax<int>(0, 100); // percentage range
IMinMax<ddateMinMax = new MinMax<DateTime>(new DateTime(1973, 10,
4), DateTime.Now); // date range
Okay, so here's the problem... what if I have the following
procedure :

public void DoSomething(object o)
{
IMinMax<mm = (IMinMax<>) o; // this doesn't work

// do something with mm.Min and mm.Max here
}

and I want to call the procedure as follows :

DoSomething(intMinMax);
DoSomething(dateMinMax);
How do we go about doing something with Min and Max? Obviously there's
a lot of meat missing in the code and I simplified it quite
unrealistically for the purpose of this newsgroup so please no
questions as to why I would want to do it... this comes up all the
time in one form or another.

I guess the real question is... once you've cast a generic interface
to an object, how do you go about extracting its information at run-
time? In my case I happen to know the type at runtime but the
following modified method still doesn't work :

public void DoSomething(Type t, object o)
{
IMinMax<tmm = (IMinMax<t>) o; // still doesn't work

// do something with mm.Min and mm.Max here
}
Regards!

Anthony

Jul 17 '07 #2

P: n/a
Sheng Jiang[MVP] <sh*********@hotmail.com.discusswrote:
Your struct (or value type) is boxed and the type information seems lost
when it is converted to object..
No, type information is certainly *not* lost when it's boxed. Just try
unboxing something to the wrong type - you'll find out soon enough.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Jul 17 '07 #3

P: n/a
It seems he did not specify the type for the generics
this program runs fine
static void Main(string[] args)
{
IMinMax<intintMinMax = new MinMax<int>(0, 100); // percentage
range
IMinMax<DateTimedateMinMax = new MinMax<DateTime>(new
DateTime(1973, 10,
4), DateTime.Now); // date range
DoSomething<int>(intMinMax);
DoSomething<DateTime>(dateMinMax);

}
public static void DoSomething<T>(object o)
{
IMinMax<Tmm = (IMinMax<T>) o;

// do something with mm.Min and mm.Max here
}

--
Sheng Jiang
Microsoft MVP in VC++
"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:MP*********************@msnews.microsoft.com. ..
Sheng Jiang[MVP] <sh*********@hotmail.com.discusswrote:
Your struct (or value type) is boxed and the type information seems lost
when it is converted to object..

No, type information is certainly *not* lost when it's boxed. Just try
unboxing something to the wrong type - you'll find out soon enough.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too

Jul 17 '07 #4

P: n/a
Sheng Jiang[MVP] <sh*********@hotmail.com.discusswrote:
It seems he did not specify the type for the generics
this program runs fine
That still doesn't mean that boxing loses type information as you
claimed.
static void Main(string[] args)
{
IMinMax<intintMinMax = new MinMax<int>(0, 100); // percentage
range
IMinMax<DateTimedateMinMax = new MinMax<DateTime>(new
DateTime(1973, 10,
4), DateTime.Now); // date range
DoSomething<int>(intMinMax);
DoSomething<DateTime>(dateMinMax);

}
public static void DoSomething<T>(object o)
{
IMinMax<Tmm = (IMinMax<T>) o;

// do something with mm.Min and mm.Max here
}
Yes, but if he changed DoSomething<Tto accept IMinMax<Tdirectly,
there'd be no need for the cast, he'd gain more compile-time type
safety, and he wouldn't have to specify the type parameter at the call
site.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Jul 18 '07 #5

P: n/a
in Managed C++, you do not have to lose static type information when you box
a value. This is something that C# does not provide.

--
Sheng Jiang
Microsoft MVP in VC++
"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:MP*********************@msnews.microsoft.com. ..
Sheng Jiang[MVP] <sh*********@hotmail.com.discusswrote:
It seems he did not specify the type for the generics
this program runs fine

That still doesn't mean that boxing loses type information as you
claimed.
static void Main(string[] args)
{
IMinMax<intintMinMax = new MinMax<int>(0, 100); //
percentage
range
IMinMax<DateTimedateMinMax = new MinMax<DateTime>(new
DateTime(1973, 10,
4), DateTime.Now); // date range
DoSomething<int>(intMinMax);
DoSomething<DateTime>(dateMinMax);

}
public static void DoSomething<T>(object o)
{
IMinMax<Tmm = (IMinMax<T>) o;

// do something with mm.Min and mm.Max here
}

Yes, but if he changed DoSomething<Tto accept IMinMax<Tdirectly,
there'd be no need for the cast, he'd gain more compile-time type
safety, and he wouldn't have to specify the type parameter at the call
site.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too

Jul 18 '07 #6

P: n/a

http://msdn2.microsoft.com/en-us/lib...05cplus_topic7
not related to this case though
--
Sheng Jiang
Microsoft MVP in VC++
"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:MP*********************@msnews.microsoft.com. ..
Sheng Jiang[MVP] <sh*********@hotmail.com.discusswrote:
It seems he did not specify the type for the generics
this program runs fine

That still doesn't mean that boxing loses type information as you
claimed.
static void Main(string[] args)
{
IMinMax<intintMinMax = new MinMax<int>(0, 100); //
percentage
range
IMinMax<DateTimedateMinMax = new MinMax<DateTime>(new
DateTime(1973, 10,
4), DateTime.Now); // date range
DoSomething<int>(intMinMax);
DoSomething<DateTime>(dateMinMax);

}
public static void DoSomething<T>(object o)
{
IMinMax<Tmm = (IMinMax<T>) o;

// do something with mm.Min and mm.Max here
}

Yes, but if he changed DoSomething<Tto accept IMinMax<Tdirectly,
there'd be no need for the cast, he'd gain more compile-time type
safety, and he wouldn't have to specify the type parameter at the call
site.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too

Jul 18 '07 #7

P: n/a
Sheng Jiang[MVP] <sh*********@hotmail.com.discusswrote:
in Managed C++, you do not have to lose static type information when you box
a value. This is something that C# does not provide.
Ah, you mean that C++ exposes the boxed type separately from the
unboxed type? Nice.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Jul 18 '07 #8

P: n/a
Hello Sheng!

Thanks for replying...

The problem with the solution you suggested is that I would have to
modify the DoSomething procedure to accept a generic type. My question
was (and given that *exact* scenario I described) how would I go about
using a generic object after it has been cast to an object and passed
as a parameter via a method that knows nothing about the generic type?
I was even generous enough to allow for the possibility of me already
knowing the generic type, but not passed in as a generic type to the
method but through a parameter of type Type as in the following :

public void DoSomething(object o, Type t)

This, of course, is a horrible example but given this exact scenario,
how would I be able to cast o back to its original form and use it?
And how would be go about doing the same if we didn't happen to have
the luxury of knowing the generic type as in the following :

public void DoSomething(object o)
{
// how do I cast o to the appropriate IMinMax<Tand use it here?
}

Regards,

Anthony

On Jul 17, 7:01 pm, "Sheng Jiang[MVP]"
<sheng_ji...@hotmail.com.discusswrote:
It seems he did not specify the type for the generics
this program runs fine
static void Main(string[] args)
{
IMinMax<intintMinMax = new MinMax<int>(0, 100); // percentage
range
IMinMax<DateTimedateMinMax = new MinMax<DateTime>(new
DateTime(1973, 10,
4), DateTime.Now); // date range
DoSomething<int>(intMinMax);
DoSomething<DateTime>(dateMinMax);

}
public static void DoSomething<T>(object o)
{
IMinMax<Tmm = (IMinMax<T>) o;

// do something with mm.Min and mm.Max here
}

--
Sheng Jiang
Microsoft MVP in VC++
"Jon Skeet [C# MVP]" <sk...@pobox.comwrote in messagenews:MP*********************@msnews.microso ft.com...
Sheng Jiang[MVP] <sheng_ji...@hotmail.com.discusswrote:
Your struct (or value type) is boxed and the type information seems lost
when it is converted to object..
No, type information is certainly *not* lost when it's boxed. Just try
unboxing something to the wrong type - you'll find out soon enough.
--
Jon Skeet - <sk...@pobox.com>
http://www.pobox.com/~skeet Blog:http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too- Hide quoted text -

- Show quoted text -

Jul 19 '07 #9

P: n/a
Hello Jon,

In reply to your post on the other duplicate thread (I had no idea it
was posted twice) as to why I didn't pass the generic type via the
generic method call :

public void DoSomething<T>(object o)
I can't do this because it mean making an assumption that object "o"
is of a certain generic type when that may not be the case. What if
it's just a regular old int? or a string? It could be an IMinMax<Tin
which case the T would come in handy, but what if it was a... let's
say, ISeries<T, U, V??

Regards,

Anthony

Jul 19 '07 #10

P: n/a
Anthony Paul <an**********@gmail.comwrote:
In reply to your post on the other duplicate thread (I had no idea it
was posted twice) as to why I didn't pass the generic type via the
generic method call :

public void DoSomething<T>(object o)

I can't do this because it mean making an assumption that object "o"
is of a certain generic type when that may not be the case. What if
it's just a regular old int? or a string? It could be an IMinMax<Tin
which case the T would come in handy, but what if it was a... let's
say, ISeries<T, U, V??
Then your cast on the first line of DoSomething is going to throw an
exception immediately.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Jul 19 '07 #11

P: n/a
Yes... that's my point, it won't work. So my question is... how does
one go about doing it?

On Jul 19, 4:32 pm, Jon Skeet [C# MVP] <sk...@pobox.comwrote:
Anthony Paul <anthonypa...@gmail.comwrote:
In reply to your post on the other duplicate thread (I had no idea it
was posted twice) as to why I didn't pass the generic type via the
generic method call :
public void DoSomething<T>(object o)
I can't do this because it mean making an assumption that object "o"
is of a certain generic type when that may not be the case. What if
it's just a regular old int? or a string? It could be an IMinMax<Tin
which case the T would come in handy, but what if it was a... let's
say, ISeries<T, U, V??

Then your cast on the first line of DoSomething is going to throw an
exception immediately.

--
Jon Skeet - <sk...@pobox.com>http://www.pobox.com/~skeet Blog:http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too

Jul 20 '07 #12

P: n/a
Anthony Paul <an**********@gmail.comwrote:
Yes... that's my point, it won't work. So my question is... how does
one go about doing it?
Doing what, exactly? You can't pretend that something implements an
interface if it doesn't.

I originally thought that your problem was not knowing what kind of
IMinMax<Tto cast to (i.e. what to use as T). If you're wanting to use
something which *isn't* an IMinMax<Tas if it is, that's a completely
different question.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Jul 20 '07 #13

P: n/a

I am looking for solution of this problem too. At this time, I use
reflection to determine the generic type of the interface and then
Invoke interface methods. But this approach generates not easy readable
code...

*** Sent via Developersdex http://www.developersdex.com ***
Jul 3 '08 #14

P: n/a
On Jul 3, 8:34*am, Sergey Zhukov <s...@ngs.ruwrote:
I am looking for solution of this problem too. At this time, I use
reflection to determine the generic type of the interface and then
Invoke interface methods. But this approach generates not easy readable
code...
When you're using reflection, the result is almost never readable
code. Generics do make it worse though - it's an extra dimension to
think about, effectively :(

Jon
Jul 3 '08 #15

P: n/a
Hi Anthony,

I've got the exact same problem. Did you find a solution in the end?

Cheers,
Sandy.
Jul 28 '08 #16

This discussion thread is closed

Replies have been disabled for this discussion.