473,385 Members | 1,930 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.

Re: Cast generic IFoo<T>

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
15 2342
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

11
by: Scott Brady Drummonds | last post by:
Hi, everyone, I've checked a couple of on-line resources and am unable to determine how reinterpret_cast<> is different from static_cast<>. They both seem to perform a compile-time casting of...
2
by: ESPNSTI | last post by:
Hi, I'm trying to use a generics dictionary with a key class that implements and needs IComparable<>. However when I attempt to use the dictionary, it doesn't appear to use the IComparable<> to...
4
by: matty.hall | last post by:
I have two classes: a base class (BaseClass) and a class deriving from it (DerivedClass). I have a List<DerivedClass> that for various reasons needs to be of that type, and not a List<BaseClass>....
3
by: Dave Booker | last post by:
Am I missing something here? It looks like the generic Queue<T> implements Enumerable<T> and ICollection but not ICollection<T>. (I want to use it in an interface that wants an ICollection<T>.) ...
27
by: Noah Roberts | last post by:
What steps do people take to make sure that when dealing with C API callback functions that you do the appropriate reinterpret_cast<>? For instance, today I ran into a situation in which the wrong...
9
by: Paul | last post by:
Hi, I feel I'm going around circles on this one and would appreciate some other points of view. From a design / encapsulation point of view, what's the best practise for returning a private...
2
by: Fred Mellender | last post by:
I am trying to use reflection to output the fields (names and values) of an arbitrary object -- an object dump to a TreeView. It works pretty well, but I am having trouble with generic lists,...
0
by: Pavel Minaev | last post by:
On Jul 24, 3:37 am, Alphapage <Alphap...@discussions.microsoft.com> wrote: Why, of course you can: public void Process<T>(IFoo<Tfoo) { ... }
4
by: =?Utf-8?B?QWxwaGFwYWdl?= | last post by:
Hello again, My last question which opened a big debate about casting such a generic interface learned me a lot, but I can't find a way because of my particular generic interface. I will shown...
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: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
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: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
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...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

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.