470,591 Members | 1,555 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 470,591 developers. It's quick & easy.

Easy Generics Question

Let's say I have an interface IScope:

internal interface IScope{}

....and I have a class that implements IScope:

internal class Scope:IScope{}

.... and I have a method that returns List<Scope>:

public List<ScopeGetScopes(){return new List<Scope>();}

.... and I'd like to pass the return value from the above method to another
method that takes a List<IScope>, say a method that looks like:

public void ProcessScopes(List<IScopescopes){}

.... I figured that a List<Scopecould be directly converted to List<IScope>
since Scope derives from IScope, but apparently I was wrong. The conversion
doesn't work, even with an explicit cast. Could someone explain the
rationale for *why* it doesn't work? My first attempt at a workaround for
this was to build the following conversion method -- something like:

public static List<UUpcastList<U,D>(List<DlstD) where D:U{
List<UlstU=new List<U>();
foreach(D d in lstD){
lstU.Add(d);
}
return lstU;
}

..this seems to work for me, but I'm still perplexed as to why the
direct conversion above fails at compile time. Any comments would be
appreciated.

Thanks..
Sep 20 '06 #1
4 1085
Drama,

Let's assume that this does work. So you have this:

List<Scope>

And in the class definition of List<Tyou have something like this
(just assuming, it doesn't matter really):

List<T>
{
private T[] items;
}

So when you use List<Scope>, items is declared as type Scope[].

Now, say you have declared a class, Scope2, which implements IScope, but
does NOT derive from Scope, like so:

class Scope2 : IScope
{}

Assuming you allowed a cast from List<Scopeto List<IScope>:

// This is not legal and will not compile.
List<IScopeiScopeList = (List<IScope>) scopeList;

And then you make the call:

iScopeList.Add(new Scope2());

It would have to fail. The reason being that while you could take a
parameter of IScope, the type itself is configured to use Scope instances.
You can't just change that. Because Scope2 doesn't derive from Scope, you
can't handle the case where fields of the parameterized type are held
internally.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Johnny Drama" <gh****@englewood.comwrote in message
news:kb******************************@giganews.com ...
Let's say I have an interface IScope:

internal interface IScope{}

...and I have a class that implements IScope:

internal class Scope:IScope{}

... and I have a method that returns List<Scope>:

public List<ScopeGetScopes(){return new List<Scope>();}

... and I'd like to pass the return value from the above method to another
method that takes a List<IScope>, say a method that looks like:

public void ProcessScopes(List<IScopescopes){}

... I figured that a List<Scopecould be directly converted to
List<IScopesince Scope derives from IScope, but apparently I was wrong.
The conversion doesn't work, even with an explicit cast. Could someone
explain the rationale for *why* it doesn't work? My first attempt at a
workaround for this was to build the following conversion method --
something like:

public static List<UUpcastList<U,D>(List<DlstD) where D:U{
List<UlstU=new List<U>();
foreach(D d in lstD){
lstU.Add(d);
}
return lstU;
}

..this seems to work for me, but I'm still perplexed as to why the
direct conversion above fails at compile time. Any comments would be
appreciated.

Thanks..

Sep 20 '06 #2
Hi Johnny,

Technically speaking, each List<Tdeclared in your code, where T differs, is created as a distinct class behind the scenes.
Although Scope implements IScope, List<Scopedoesn't derive from List<IScope>. Each are distinct classes that do not share the
same inheritance chain beyond IList and its derived interfaces. i.e., It's like casting an apple into an orange, so to speak. The
fact that the generic Types share the same inheritance chain is irrelevant.

This might be confusing since Scope[] may be passed to a method that expects IScope[], but that is because Array semantics are
handled by the runtime. The generic List class provides array semantics on a higher-level then Array and the runtime is unaware of
such an implementation and so treats it as it would any other class in the framework.

--
Dave Sexton

"Johnny Drama" <gh****@englewood.comwrote in message news:kb******************************@giganews.com ...
Let's say I have an interface IScope:

internal interface IScope{}

...and I have a class that implements IScope:

internal class Scope:IScope{}

... and I have a method that returns List<Scope>:

public List<ScopeGetScopes(){return new List<Scope>();}

... and I'd like to pass the return value from the above method to another method that takes a List<IScope>, say a method that
looks like:

public void ProcessScopes(List<IScopescopes){}

... I figured that a List<Scopecould be directly converted to List<IScopesince Scope derives from IScope, but apparently I was
wrong. The conversion doesn't work, even with an explicit cast. Could someone explain the rationale for *why* it doesn't work? My
first attempt at a workaround for this was to build the following conversion method -- something like:

public static List<UUpcastList<U,D>(List<DlstD) where D:U{
List<UlstU=new List<U>();
foreach(D d in lstD){
lstU.Add(d);
}
return lstU;
}

..this seems to work for me, but I'm still perplexed as to why the direct conversion above fails at compile time. Any comments
would be appreciated.

Thanks..

Sep 20 '06 #3
In microsoft.public.dotnet.languages.csharp Johnny Drama <gh****@englewood.comwrote:
Let's say I have an interface IScope:

internal interface IScope{}

...and I have a class that implements IScope:

internal class Scope:IScope{}

... and I have a method that returns List<Scope>:

public List<ScopeGetScopes(){return new List<Scope>();}
List<ScopeoldScopes = new List<Scope>();
oldScopes.Add(new Scope());
List<IScopescopes = new List<IScope>(oldScopes);

I hope that helps you out.

--
Thomas T. Veldhouse
Key Fingerprint: 2DB9 813F F510 82C2 E1AE 34D0 D69D 1EDC D5EC AED1
Sep 20 '06 #4
Thanks, guys!! I now understand.

much appreciated,

Johnny
Sep 20 '06 #5

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

27 posts views Thread by Bernardo Heynemann | last post: by
6 posts views Thread by Jules Winfield | last post: by
13 posts views Thread by Luc Vaillant | last post: by
1 post views Thread by Peter Kirk | last post: by
18 posts views Thread by riftimes | last post: by
11 posts views Thread by hammad.awan_nospam | last post: by
1 post views Thread by Kevin S. Goff | last post: by
7 posts views Thread by SpotNet | last post: by
13 posts views Thread by rkausch | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.