C#将派生的泛型类型转换为父类

Hec*_*nos 3 c# generics downcast

在我问我的问题之前,这是我的结构:

public class Data : ScriptableObject {...}
public class ItemData : Data {...}
public class WeaponData : ItemData {...}

public abstract class Item<T> : Visual<T> where T : ItemData {...}
public class Weapon<T> : Item<T> where T : WeaponData {...}
Run Code Online (Sandbox Code Playgroud)

当我创建一个Weapon对象并将其分配给我时,我收到一个错误(无法从源类型转换为目标类型)Item<ItemData>.

Weapon<Foo> weapon = new Weapon<Foo>();
Item<ItemData> other = weapon;
Run Code Online (Sandbox Code Playgroud)

这是为什么?

Dav*_*d L 5

在C#中,协方差(将派生类型分配给基类型)不能应用于泛型类.因此,您需要在新接口上使用out参数修饰符来应用专门标记为协变的IItem接口.

但是,这本身是不够的.当有一个泛型类型参数可以是它继承的任何东西时,你没有办法告诉Item它将允许Weapon为它分配一个实例.这使编译器陷入困境,因为它无法向您保证关系是有效的.但是,如果您应用新界面,则允许演员表.WeaponItemDataIItemDataItemData

void Main()
{
    Weapon<Foo> weapon = new Weapon<Foo>();
    IItem<ItemData> other = weapon;
}

public interface IItem<out T> {}
public interface IItemData {}

public class Foo : WeaponData {}

public class Data : ScriptableObject {}
public class ItemData : Data, IItemData {}
public class WeaponData : ItemData {}

public abstract class Item<T> : Visual<T>, IItem<T> where T : IItemData {}
public class Weapon<T> : Item<T> where T : WeaponData {}

public class ScriptableObject {}
public class Visual<T> {}
Run Code Online (Sandbox Code Playgroud)

这需要Item<T>更新以限制为IItemData而不是约束到具体类型.