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

Re: Cast generic IFoo<T>

P: n/a
Don't mistake generic type for what you would like them to be!!

IFoo<Ahas nothing in common with IFoo<B>!
They are completely different type create dynamically at runtime.

What you ask is a bit akin to ask: "the System.Web.UI and
System.Windows.Controls namespace both contains a Control class, could I use
one in place of the other? common they have the same name!"

If you want to use a method common to both you should do as Alun suggested.
Inherhit IFoo<t: IFoo.

Surprise, surprise, it's exactly what they did at Microsoft, you'll notice,
for exemple, that
IList<T: IList
IEnumerator<T: IEnumerator
ICollection<T: ICollection
etc....

Jul 24 '08 #1
Share this Question
Share on Google+
15 Replies


P: n/a
On Jul 24, 1:30*am, "Lloyd Dupont" <some...@somewhere.netwrote:

<snip>
Surprise, surprise, it's exactly what they did at Microsoft, you'll notice,
for exemple, that
IList<T: IList
IEnumerator<T: IEnumerator
ICollection<T: ICollection
etc....
That's only true for IEnumerator<T>. IList<Tdoesn't extent IList and
ICollection<Tdoesn't extend ICollection.

That said, making the generic interface extend a non-generic one is a
fine solution in many cases. It's what I'm doing at the moment with
Protocol Buffers...

Jon
Jul 24 '08 #2

P: n/a
On Wed, 23 Jul 2008 22:46:41 -0700, Jon Skeet [C# MVP] <sk***@pobox.com>
wrote:
[...]
That said, making the generic interface extend a non-generic one is a
fine solution in many cases.
Noting, IMHO, that doing so assumes the non-generic interface already
exists. I'm not convinced that I'd create a non-generic interface for the
purpose (and as far as I know, Microsoft didn't either), since doing so
pretty much winds up intentionally defeating the point of using the
generic in the first place.

Whatever code's already using the generic interface in its concrete form
must already know the type parameter, so making a generic method to
support the generic interface shouldn't be a problem at all (assuming it's
not suitable for the method itself to be declared using a concrete form of
the generic interface, which I think usually would be the case).

Pete
Jul 24 '08 #3

P: n/a
On Jul 24, 6:57 am, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
wrote:
That said, making the generic interface extend a non-generic one is a
fine solution in many cases.

Noting, IMHO, that doing so assumes the non-generic interface already
exists.
Not necessarily.
I'm not convinced that I'd create a non-generic interface for the
purpose (and as far as I know, Microsoft didn't either), since doing so
pretty much winds up intentionally defeating the point of using the
generic in the first place.
Only for some cases. It depends whether the parts of the API you're
interested in depend on the type parameter. For instance, it would be
handy for my current work if IList<Timplemented a (mythical)
interface called ICountable with a Count property. In my current code
I sometimes need to get the count of an object which I know is an
IList<Somethingbut I don't know what Something is at compile-time.
Whatever code's already using the generic interface in its concrete form
must already know the type parameter, so making a generic method to
support the generic interface shouldn't be a problem at all (assuming it's
not suitable for the method itself to be declared using a concrete form of
the generic interface, which I think usually would be the case).
Not necessarily - see my example above. In my case I receive the
object as just "object" and have to cast to *something* - but there's
no appropriate type I can cast to without the type information.

In addition, I need to suppose situations where everything's dynamic -
which means my nongeneric API is actually just as rich in terms of
abilities as my generic API, it just lacks the precise type safety.
That means a lot of explicit interface implementation etc, which isn't
terribly nice but it's the best way available in the situation. I
acknowledge that it's not a terribly common situation though...

(The code is available on github -
http://github.com/jskeet/dotnet-prot...rotocolBuffers
and look at IMessage.cs and IBuilder.cs.)

Jon
Jul 24 '08 #4

P: n/a
For info, I've used the same non-generic/generic inherited pair many
times, for example scenarios like property bag implementations. In
reality it isn't a problem; type safety is still enforced by the
underlying type. Typically the generic interface will re-declare ("new")
some (but not all) members with more specific versions.

For example: just because List<Timplements IList, and IList has
Add(object), that doesn't imply that you can *actually* add a string to
a List<intby cheating through the IList facet.

Marc
Jul 24 '08 #5

P: n/a
On Jul 24, 11:12*am, Marc Gravell <marc.grav...@gmail.comwrote:
For example: just because List<Timplements IList, and IList has
Add(object), that doesn't imply that you can *actually* add a string to
a List<intby cheating through the IList facet.
Funnily enough, I hadn't spotted that List<Timplements IList. I
looked at IList<Tbut not List<T>.
Hmm. That *might* be very handy...

Jon
Jul 24 '08 #6

P: n/a
On Wed, 23 Jul 2008 23:30:37 -0700, Jon Skeet [C# MVP] <sk***@pobox.com>
wrote:
[...]
Only for some cases. It depends whether the parts of the API you're
interested in depend on the type parameter. For instance, it would be
handy for my current work if IList<Timplemented a (mythical)
interface called ICountable with a Count property. In my current code
I sometimes need to get the count of an object which I know is an
IList<Somethingbut I don't know what Something is at compile-time.
If you know it's an IList<Something>, then you can use it generically and
have the call chain provide the type. That's my point.

As convenient? No, I admit not. But IMHO it's a better approach and
should be used unless it's completely impossible for some reason (having a
hard time envisioning such a scenario, but happy to give the benefit of
the doubt with respect to ruling something out completely :) ).
>Whatever code's already using the generic interface in its concrete form
must already know the type parameter, so making a generic method to
support the generic interface shouldn't be a problem at all (assuming
it's
not suitable for the method itself to be declared using a concrete form
of
the generic interface, which I think usually would be the case).

Not necessarily - see my example above. In my case I receive the
object as just "object" and have to cast to *something* - but there's
no appropriate type I can cast to without the type information.
If all you know is "object", then it doesn't really matter whether your
"ICountable" interface is inherited by "IList<T>" or is simply implemented
as a separate interface. I don't think it's necessary for the generic
interface to _inherit_ a non-generic interface for that purpose.

But in any case, this isn't comparable to the OP's scenario, which is all
I was commenting on (thus, my statement in my previous reply that included
the phrase "for the purpose").
In addition, I need to suppose situations where everything's dynamic -
which means my nongeneric API is actually just as rich in terms of
abilities as my generic API, it just lacks the precise type safety.
That means a lot of explicit interface implementation etc, which isn't
terribly nice but it's the best way available in the situation. I
acknowledge that it's not a terribly common situation though...
I admit, I'm not really clear on what "where everything's dynamic" means
in a precise way. However, I'll again suggest that's not a situation
comparable to that presented in the original post.

Pete
Jul 24 '08 #7

P: n/a
On Thu, 24 Jul 2008 03:12:53 -0700, Marc Gravell <ma**********@gmail.com>
wrote:
[...]
For example: just because List<Timplements IList, and IList has
Add(object), that doesn't imply that you can *actually* add a string to
a List<intby cheating through the IList facet.
Well, you can't at run-time. But you can write code to do so that will
compile just fine.

Anyway, there seems to be some confusion that I'm saying "never inherit a
non-generic interface", which wasn't my point at all. As you all should
know, I try as hard as I can to never say "never"; there's almost always
an exception to the rule.

But with regards to the original problem, I see no need to do that.

Pete
Jul 24 '08 #8

P: n/a
On Jul 24, 5:36*pm, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
wrote:
If you know it's an IList<Something>, then you can use it generically and*
have the call chain provide the type. *That's my point.
No, I can't. I know it will be IList<Somethingin a non-compiler-
provable way, but I can't determine (at compile-time) which type it
will be. So I can't cast to it.
As convenient? *No, I admit not. *But IMHO it's a better approach and*
should be used unless it's completely impossible for some reason (having a *
hard time envisioning such a scenario, but happy to give the benefit of *
the doubt with respect to ruling something out completely :) ).
When you specify a type, e.g. as a return type or a parameter type,
you can only specify one type. You can't say "It has to take something
which implements both ICountable and IList<T>" - not unless you
introduce another generic type parameter just for that purpose, which
certainly isn't always practical.
Not necessarily - see my example above. In my case I receive the
object as just "object" and have to cast to *something* - but there's
no appropriate type I can cast to without the type information.

If all you know is "object", then it doesn't really matter whether your *
"ICountable" interface is inherited by "IList<T>" or is simply implemented *
as a separate interface.
Yes it does - because I can guarantee (in my situation) that it will
have been created as an IList<Tsomewhere. Even if the ICountable
interface existed, however I couldn't necessarily ensure that the
implementation of IList<Talso implemented ICountable.
>*I don't think it's necessary for the generic *
interface to _inherit_ a non-generic interface for that purpose.
It really, really would have helped in my situation.
But in any case, this isn't comparable to the OP's scenario, which is all*
I was commenting on (thus, my statement in my previous reply that included *
the phrase "for the purpose").
I'm not sure we know enough about the OP's scenario to say for sure.

Jon
Jul 24 '08 #9

P: n/a
On Thu, 24 Jul 2008 09:53:29 -0700, Jon Skeet [C# MVP] <sk***@pobox.com>
wrote:
On Jul 24, 5:36*pm, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
wrote:
>If you know it's an IList<Something>, then you can use it generically
and *
have the call chain provide the type. *That's my point.

No, I can't. I know it will be IList<Somethingin a non-compiler-
provable way, but I can't determine (at compile-time) which type it
will be. So I can't cast to it.
If you don't know it in a compiler-provable way, then again: I think
that's not comparable to the OP's situation (his code specifically shows
an explicit type declaration).
[...]
>If all you know is "object", then it doesn't really matter whether your
"ICountable" interface is inherited by "IList<T>" or is simply
implemented *
as a separate interface.

Yes it does - because I can guarantee (in my situation) that it will
have been created as an IList<Tsomewhere. Even if the ICountable
interface existed, however I couldn't necessarily ensure that the
implementation of IList<Talso implemented ICountable.
At the risk of belaboring a point I think is irrelevant to the original
question: but why would that matter?

If as a matter of the actual definition for IList<Tit needs to inherit
ICountable, then sure...inherit away. But if all we've got is code that
wants an ICountable, then it shouldn't care at all whether that's part of
IList<Tor something else. If you already know for sure it's created as
IList<T>, then even better, should you happen to also want to use the
instance as an IList<T>. But that doesn't stop you from reinterpreting
the instance reference in two different ways to support two different
interfaces.

Again, I don't disagree that it's simpler to keep one variable than two,
but I don't see this as implying that the best solution is to create a
whole new type just for that purpose. And of course, I definitely don't
see that as a required approach to the original question.
[...]
I'm not sure we know enough about the OP's scenario to say for sure.
As is often the case, it's true that we can't be sure we know enough. I
agree with that.

But I feel reasonably confident enough to make statements based on the
question as stated. In particular, it seems pretty clear to me that he's
not looking to do any casting; he's got an object instance he wants to
pass, but without the generic decoration. In other words, the caller
already knows we're dealing with the generic type.

If his post has misrepresented the situation, then yes...there may be more
to the solution than just creating a generic method, and perhaps even
there would be a justification for creating a new non-generic interface.
But I think that given the code posted so far, a generic method is a more
appropriate approach than creating a new type.

Pete
Jul 24 '08 #10

P: n/a
On Thu, 24 Jul 2008 12:44:22 -0700, Jon Skeet [C# MVP] <sk***@pobox.com>
wrote:
[...]
That's precisely what I've been proposing. I don't know if you're a Red
Dwarf fan, but there's an episode called "White Hole" which has the
perfect conversation here :)
I'm a fan, but haven't watched enough episodes to catch the reference.
I've gone off to read the script now... :)
Jul 24 '08 #11

P: n/a
On Jul 24, 8:53*pm, "Jon Skeet [C# MVP]" <sk...@pobox.comwrote:
When you specify a type, e.g. as a return type or a parameter type,
you can only specify one type. You can't say "It has to take something
which implements both ICountable and IList<T>" - not unless you
introduce another generic type parameter just for that purpose, which
certainly isn't always practical.
Why isn't it practical? So far as I can see, it's precisely what is
needed. Overly verbose, perhaps, especially if we don't actually need
to refer to T anywhere else (wish we had a placeholder like Java's "?"
there), but on the whole, it makes sense. Generic parameter covariance
and contravariance at declaration site, as promised in C# 4.0, is of
limited utility (because if we take IList<Tfor example, that T will
be invariant - so we don't get anything), and the only other approach
to proper granularity is to have one interface per method/property....

The bigger deal there is the lack of contravariance - the "? super T"
constraint in Java. Without it, as it stands, it's simply impossible
to write a generic method that takes "any IList<to which an instance
of T can be added".
Jul 25 '08 #12

P: n/a
Jon: "so what is it?"

Jon/Pete: re knowing it is an IList<T>, but not knowing the T - this
happens a lot if your code is processing rtti from other types. As it
happens, Jon and I are looking at the same problem (in different
ways), so I know very well that in this case you can't know the T -
but this is very common anyway when working with reflection /
ComponentModel.

For my own version of the problem, I cheat : my /real/ code uses
IList<T>, and the other code uses MakeGenericMethod to invoke the
typed version with the appropriate T; this works well, but it is only
appropriate if you are doing pre-processing (it isn't something you'd
want to do repeatedly in a tight loop for example).

Jon: "so what is it?"

Marc
Jul 25 '08 #13

P: n/a
Marc Gravell <ma**********@gmail.comwrote:
Jon: "so what is it?"
It's a *white* hole, sir.
Jon: "so what is it?"
I believe we've just reached the middle of this conversation.
(From memory, last watched about 10 years ago, so don't hold me to the
exact words...)

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Jul 25 '08 #14

P: n/a
Pavel Minaev <in****@gmail.comwrote:
On Jul 24, 8:53*pm, "Jon Skeet [C# MVP]" <sk...@pobox.comwrote:
When you specify a type, e.g. as a return type or a parameter type,
you can only specify one type. You can't say "It has to take something
which implements both ICountable and IList<T>" - not unless you
introduce another generic type parameter just for that purpose, which
certainly isn't always practical.
Why isn't it practical?
Well, for one thing that information can't be captured by the compiler
at the client side. If I declare a generic method like this:

T Foo() where T : IList<T>, ICountable

then in the caller, if I want to use both aspects of it, I will need to
cast at some point, which will mean a runtime check, even though really
we know that it will always be valid. It's a pain.

In addition, introducing extra levels of generic methods etc ends up
with code which can be very confusing. Just making one interface derive
from another - particularly when it adds no cost to the implementer -
is much simpler.

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Jul 25 '08 #15

P: n/a
On Jul 25, 10:34*pm, Jon Skeet [C# MVP] <sk...@pobox.comwrote:
Well, for one thing that information can't be captured by the compiler
at the client side. If I declare a generic method like this:

T Foo() where T : IList<T>, ICountable

then in the caller, if I want to use both aspects of it, I will need to
cast at some point, which will mean a runtime check, even though really
we know that it will always be valid. It's a pain.
Technically, you can capture T in the above example with complete
(and static) type decorations if you just pass on the returned value
to your own generic method at call site - but I agree that it is
rather a mess. One could probably write helpers, like this:

struct GenericResult<T1, T2>
{
public T1 o1;
public T2 o2;

public GenericResult(T o) where T: T1, T2
{
o1 = o; o2 = o;
}
}
// overloads for up to N generic parameters ...

But it is still messy. This is only a problem with return types of
methods though, not parameters.

It would really be much more convenient if we could just get & and |
combinators on types. One can dream...
Jul 25 '08 #16

This discussion thread is closed

Replies have been disabled for this discussion.