Windows Vista Forums
Vista Forums Home Join Vista Forums Windows 7 Forum Vista Tutorials Tags
Welcome to Windows Vista Forums. Our forum is dedicated to helping you find solutions with any problems, errors or issues you are experiencing with Windows Vista. The Vista forum also covers news and updates and has an extensive Windows Vista tutorial section that covers a wide range of tips and tricks.

Go Back   Vista Forums > Misc Newsgroups > .NET General

Vista - Upcasting to List<ISomeInteface> ?

Reply
 
Old 04-02-2008   #1 (permalink)
Jules Winfield


 
 

Upcasting to List<ISomeInteface> ?

One thing I've never really understood about C# is the inability to upcast
generics based on templated type. If I have:

interface ISomeInterface{}

and

class SomeClass:ISomeInterface{}

and I have a List<SomeClass>, it seems like I should be able to assign it,
or at least cast it, to a List<ISomeInterface>.... but I can't. It won't
compile.

As it stands, every time I own a List<SomeClass> and want to pass it to a
method that accepts a List<ISomeInterface>, I have to create a new
List<ISomeInterface> and populate it with the data from List<SomeClass>.
I've created a template method to handle the work for me but I'd like to
avoid the needless CLR overhead involved in creating these intermediate
List<> objects.

Do you have a more efficient approach that I could employ?

Jules



My System SpecsSystem Spec
Old 04-02-2008   #2 (permalink)
Peter Duniho


 
 

Re: Upcasting to List<ISomeInteface> ?

On Wed, 02 Apr 2008 10:41:31 -0700, Jules Winfield
<Jules.Winfield@xxxxxx> wrote:
Quote:

> One thing I've never really understood about C# is the inability to
> upcast
> generics based on templated type. If I have:
>
> interface ISomeInterface{}
>
> and
>
> class SomeClass:ISomeInterface{}
>
> and I have a List<SomeClass>, it seems like I should be able to assign
> it,
> or at least cast it, to a List<ISomeInterface>.... but I can't. It won't
> compile.
Nor should it, IMHO. You can search this newsgroup for "generic
covariance" to see more detailed explanations. But the short answer is:

interface ISomeInterface { }
class SomeClass : ISomeInterface { }
class SomeOtherClass : ISomeInterface { }

List<SomeClass> list1 = new List<SomeClass>();
List<ISomeInterface> list2 = list1; // suppose this were allowed

list2.Add(new SomeOtherClass());

Then all of the sudden, you've got an instance of SomeOtherClass in your
List<SomeClass>. Hopefully it's obvious why that's bad.
Quote:

> As it stands, every time I own a List<SomeClass> and want to pass it to a
> method that accepts a List<ISomeInterface>, I have to create a new
> List<ISomeInterface> and populate it with the data from List<SomeClass>.
> I've created a template method to handle the work for me but I'd like to
> avoid the needless CLR overhead involved in creating these intermediate
> List<> objects.
>
> Do you have a more efficient approach that I could employ?
My understanding is that the .NET run-time actually supports covariance in
generics. So maybe there's a non-C# way around the issue, if you really
want to do that.

It seems to me that an alternative route would be to maintain your list as
a List<ISomeInterface> in the first place. Yes, the
"least-common-denominator" approach sacrifices some of the type safety of
generics, but then that's what you're asking to do in the first place. If
the overhead of converting instances of the List<T> class back and forth
bothers you that much, then perhaps that's the solution you should take.

Pete
My System SpecsSystem Spec
Old 04-02-2008   #3 (permalink)
Henning Krause [MVP - Exchange]


 
 

Re: Upcasting to List<ISomeInteface> ?

Hello,

with .NET 3.5 and its LINQ extenstion methods you can write

myList.Cast<ISomeInterface>().

Kind regards,
Henning Krause

"Jules Winfield" <Jules.Winfield@xxxxxx> wrote in message
news:buGdnXs975nWWG7anZ2dnUVZ_jOdnZ2d@xxxxxx
Quote:

> One thing I've never really understood about C# is the inability to upcast
> generics based on templated type. If I have:
>
> interface ISomeInterface{}
>
> and
>
> class SomeClass:ISomeInterface{}
>
> and I have a List<SomeClass>, it seems like I should be able to assign it,
> or at least cast it, to a List<ISomeInterface>.... but I can't. It won't
> compile.
>
> As it stands, every time I own a List<SomeClass> and want to pass it to a
> method that accepts a List<ISomeInterface>, I have to create a new
> List<ISomeInterface> and populate it with the data from List<SomeClass>.
> I've created a template method to handle the work for me but I'd like to
> avoid the needless CLR overhead involved in creating these intermediate
> List<> objects.
>
> Do you have a more efficient approach that I could employ?
>
> Jules
>
My System SpecsSystem Spec
Old 04-02-2008   #4 (permalink)
Jules Winfield


 
 

Re: Upcasting to List<ISomeInteface> ?

>>>>
Then all of the sudden, you've got an instance of SomeOtherClass in your
List<SomeClass>. Hopefully it's obvious why that's bad.
<<<<

Ah, yes, this makes sense. I should've thought of that. Thanks for the
explanation.


My System SpecsSystem Spec
Old 04-02-2008   #5 (permalink)
John B


 
 

Re: Upcasting to List<ISomeInteface> ?

Jules Winfield wrote:
Quote:

> One thing I've never really understood about C# is the inability to upcast
> generics based on templated type. If I have:
>
> interface ISomeInterface{}
>
> and
>
> class SomeClass:ISomeInterface{}
>
> and I have a List<SomeClass>, it seems like I should be able to assign it,
> or at least cast it, to a List<ISomeInterface>.... but I can't. It won't
> compile.
>
<...>
Quote:

> Do you have a more efficient approach that I could employ?
>
You could declare your method to use IEnumerable<ISomeInterface> instead.
Then when you need to pass your List<SomeClass> you can do as such:

List<SomeClass> myList = LoadList();
SomeMethod(myList.ToArray());

--- void SomeMethod(IEnumerable<ISomeInterface

Arrays are Covariant in c# so this will work.


HTH
JB
My System SpecsSystem Spec
Old 04-03-2008   #6 (permalink)
Marc Gravell


 
 

Re: Upcasting to List<ISomeInteface> ?

As an aside, there is another useful trick; use a generic method and
type-inference; an example is below - note that in this case I could also
replace List<T> with IList<T> or IEnumerable<T>...

The point is: it isn't that "List<Foo> inherits from List<IFoo>", but rather
that you want a list of [things] where those [things] inherit from IFoo -
"List<T> where T : IFoo"

Marc

using System;
using System.Collections.Generic;

interface IFoo {
int Bar {get;set;}
}
class Foo : IFoo {
public int Bar {get;set;}
}
static class Program
{
static void Main()
{
List<Foo> foos = new List<Foo> {
new Foo {Bar = 5}, new Foo {Bar = 7}
};
//SomeMethod(foos); // ERROR doesn't compile
SomeOtherMethod(foos);
}
static void SomeMethod(List<IFoo> foos) {}
static void SomeOtherMethod<T>(List<T> foos) where T : IFoo
{
foreach (T foo in foos)
{
Console.WriteLine(foo.Bar);
}
}
}



My System SpecsSystem Spec
Old 04-03-2008   #7 (permalink)
Jules Winfield


 
 

Re: Upcasting to List<ISomeInteface> ?

thanks for the suggestions; they're much appreciated and they've given me
more of an appreciation for the way c# is designed.


My System SpecsSystem Spec
Reply

Thread Tools


Similar Threads
Thread Forum
Creating a distribution list from a long cc list Vista mail
Problem copying list of contacts into a new group list Vista mail
add my contact list to safe senders list Vista mail
converting email list to mailing list .NET General
Network List Service is missing from the list of services Network & Sharing


Vista Forums is an independent web site and has not been authorized,
sponsored, or otherwise approved by Microsoft Corporation.
"Windows Vista", the Start Orb, and related materials are trademarks of Microsoft Corp.
© Designer Media Ltd

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46