Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Question
Thursday, March 26, 2009 5:44 AM
I've a method with a property of type List<ChildClass>. I'm calling getting the value of this with reflection, and I get an object, when debug it shows that the object has correct data. When i try to cast the object to List<IMyInterface> (ChildClass implements IMyInterface> i get the following error:
Cannot cast 'objData' (which has an actual type of 'System.Collections.Generic.List<ChildClass>') to 'System.Collections.Generic.List<IMyInterface>'
what is that i'm doing wrong???
All replies (6)
Thursday, March 26, 2009 2:26 PM âś…Answered | 2 votes
Eyal-Shilony has a good description of the underlying problem. BTW, this is one thing that they're looking at fixing in .NET 4.0.
To fix this problem now, you can cast to (non-generic) IList and then use LINQ to cast each object:
IList objList = (IList)objData; |
int count = objList.Count; // The LINQ conversions will lose this information |
IEnumerable<IMyInterface> list = objList.Cast<IMyInterface>(); |
-Steve
Thursday, March 26, 2009 7:19 AM
Hello,
Nothing is wrong, except the fact you're trying to cast a lemon tree to an ordinary tree of citrus fruits, having a collection of A and a collection of IA are two different things regardless of A implementing IA.
So in that case you can have a collection of IA, which will allow you to add objects of A.
.Net developer and software consultant.
Friday, March 27, 2009 12:53 AM
Here is the example:
List<string> list = new List<string>();
list.Add("Hi");
list.Add("Bye");
object obj = list;
I can do simply casting here as it's the same type.
list = (List<string>)o;
And loop through list, and print values. It will print:
Hi
Bye
But if it's not the same type as in question (implement interface), we can do exactly suggested by Stephen.
Here also LINQ comes for help.
IList iList = (IList)obj;
IEnumerable<string> list2 = iList.Cast<string>();
foreach (string str in list2)
{
Label1.Text += str + "</br>";
}
And loop through list, and print values. It will print:
Hi
Bye
Hope this helps.
Friday, March 27, 2009 1:28 AM
Stephen, do you know how they plan on fixing this in .Net 4.0?
I find this quite annoying when you have a method from another library with this signature:
public void DoSomething(List<object>); |
If you happen to have a collection of MyClass, you have to use a temporary collection:
List<MyClass> items = // your original list; |
var copy = new List<object>(); |
items.ForEach(o => copy.Add(o)); |
externalLib.DoSomething(copy); |
I understand that MyClass and object are different types, but why can't there be a type-safe implicit conversion towards a list of the parent type? If a method want to process a list of trees, I don't see anything wrong with giving it a list of lemon trees.
Or maybe at least a type-safe extension method?
DoSomething( items.AsList<object>() ); |
Friday, March 27, 2009 2:28 PM
It's called "genetic variance", and currently they're planning on supporting explicit covariance and contravariance.
Here's a high-level overview of what will be allowed for collection variance:
**Generic Variance in C# 4.0
**http://kohari.org/2008/10/28/generic-variance-in-c-40/
and delegate variance (note that a more limited form of delegate variance is allowed in the current language):
LINQ Farm: Covariance and Contravariance in C# 4.0
http://blogs.msdn.com/charlie/archive/2008/10/28/linq-farm-covariance-and-contravariance-in-visual-studio-2010.aspx
and, finally, a complete 11-part series of posts explaining way more than anyone needs to know at this point:
**Eric Lippert on Covariance and Contravariance
**http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx
-Steve
Friday, March 27, 2009 2:35 PM
Romain Prieto said:
Stephen, do you know how they plan on fixing this in .Net 4.0?
The C# Futures page has all this information.
http://code.msdn.microsoft.com/csharpfuture
Or maybe at least a type-safe extension method?
DoSomething( items.AsList<object>() ); |
These two methods may help.
Enumerable.OfType
Enumerable.Cast
Types with generic parameters are defined at runtime in memory with the type parameters filled in. They're not contra-variant or co-variant.
Arrays, however, are covariant in C#.
int[] can be cast to IList<object> and IList<int> as well.
David Morton - http://blog.davemorton.net/