问题
I've got an object, which I'll call MyObject. It's a class that controls a particular data row.
I've then got a collection class, called MyObjectCollection:
public class MyObjectCollection : List<MyObject> {}
Why can I not do the following:
List<MyObject> list = this.DoSomethingHere();
MyObjectCollection collection = (MyObjectCollection)list;
Thanks in advance.
Edit: The error is InvalidCastException
回答1:
My guess is that DoSomethingHere
doesn't return an instance of MyObjectCollection
.
Let's get rid of all the generics etc here, as they're not relevant. Here's what I suspect you're trying to do:
public static object CreateAnObject()
{
return new object();
}
object o = CreateAnObject();
string s = (string) o;
That will fail (at execution time) and quite rightly so.
To bring it back to your code, unless DoSomethingHere
actually returns a MyObjectCollection
at execution time, the cast will fail.
回答2:
Because a List<MyObject>
is not a MyObjectCollection. The reverse is true: you could cast a MyObjectCollection to a List because MyObjectCollection inherits from List<MyObject>
and thus, for all intents and purposes, IS A List<MyObject>
.
The only thing you can do is to define a constructor on MyObjectCollection that takes an Ienumerable as a parameter and initalizes itself with the data in the other one, but that will make a new object containing the same data:
public class MyObjectCollection : List<MyObject>
{
public MyObjectCollection(IEnumerable<MyObject> items)
{
Addrange(items);
}
}
UPDATE: As noted in the comment, you COULD have the cast succeed at runtime, provided that DoSomething actually returns an instance of MyObjectCollection. If it does, the object effectively is a MyObjectCollection, and the cast is completely legal.
I'd have to say, it is bad practice in my view to upcast something like that. If the function returns a List, you should not rely on a specific implementation of List. Either modify the return type of DoSomething, if you own that function, and return a MyObjectCollection, or deal with it as a list.
回答3:
Without knowing what exactly is created inside DoSomething() we have to assume either:
You have a misunderstanding about the inheritence in .Net.
you have
A : B
B DoSomething()
{
return new B();
}
// then this is
B b = new B();
A a = (A)b;
Clearly b is a B but not an A. B might look much like A but it is not (if you traverse the parentage of b you won't find A anywhere)
This is true irrespective of the Generics involved (though that sometimes can cause situations where something that could work doesn't see the co-contra variance in c# 4.0)
or
A : B
B DoSomething()
{
return new A();
}
// then this is
B b = new A();
A a = (A)b;
Which in the absence of Generics will work.
回答4:
You can't do it because (I guessing) the list instance returned from DoSomethingHere isn't derived from MyObjectCollection
回答5:
You could create an implicit operator that would allow you to convert between your object and the list. You would need an constructor that takes a list and to property that returns the underlaying list.
public static implicit operator List<MyObject>(MyObjectCollection oCollection)
{
//Convert here
return MyObjectCollection.BaseList;
}
public static implicit operator MyObjectCollection(List<MyObject> oList)
{
//Convert here
return new MyObjectCollection(oList);
}
来源:https://stackoverflow.com/questions/768225/c-sharp-why-can-i-not-cast-a-listmyobject-to-a-class-that-inherits-from-list