C# - Why can I not cast a List<MyObject> to a class that inherits from List<MyObject>?

有些话、适合烂在心里 提交于 2019-12-25 04:33:30

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!