【问题标题】:Storing list of generic class of derived objects存储派生对象的通用类列表
【发布时间】:2016-01-15 19:55:17
【问题描述】:

例如,如何存储所有使用派生自同一基类的类型的 DataContainer 列表。

public class Animal {}
public class Cat : Animal {}
public class Dog : Animal {}
public class DataContainer <TData> where TData : Animal {
    TData innerObject = new TData ();
    public TData GetData () {
        return innerObject;
    }
}

public class DataManager {
    static void Main () {
        DataContainer<Cat> CatData = new DataContainer<Cat> ();
        DataContainer<Dog> DogData = new DataContainer<Dog> ();
        var AnimalData = new List<DataContainer<Animal>> ();
        AnimalData.Add (CatData);
        AnimalData.Add (DogData);
        for (int i = 0; i < AnimalData.Count; i++) {
            Animal animal = AnimalData[i].GetData ();
        }
    }
}

如果不能使用泛型类,那么可以使用数组吗?

编辑:收到此错误:ArrayTypeMismatchException: Source array type cannot be assigned to destination array type. 这会导致 ArrayTypeMismatchException:

public interface IDataContainer <out TData> where TData : Animal {

}
public class DataContainer <TData> : IDataContainer<TData> where TData : Animal {

}

public class Tester () {
    static void Main () {
        var AnimalData = new List<DataContainer<Animal>> ();
        var CatData = new DataContainer<Cat> ();
        AnimalData.Add (CatData as IDataContainer<Animal>); //Error
    }
}

在 Unity 5.2 中运行

【问题讨论】:

    标签: c# generics inheritance polymorphism


    【解决方案1】:

    问题是您需要泛型类具有covariant 类型参数。

    你只能在接口上这样做,所以创建一个:

    public interface IDataContainer <out TData> where TData : Animal 
    {
        TData GetData ();
    }
    

    注意使用outTData 标记为协变。现在让你的DataContainer 类实现接口,当你在客户端代码中保留一个引用时,确保它是一个IDataContainer。现在它应该可以让您按预期存储它了。

    请注意协变接口有特殊要求,即泛型类型参数不能用作任何方法的参数类型(更多信息请参见 MSDN 链接)。

    【讨论】:

    • 完美运行!谢谢!
    • 强制转换有效,但有没有办法将协变对象添加到集合中?
    • @user196399 不确定您的意思(我的示例中没有强制转换)也许提供一个代码示例,或者提出一个新问题并给我发送链接?
    • 就像在问题的代码中一样,我想将协变对象添加到列表或某种集合中,以便可以遍历所有 DataContainer。 AnimalData.Add (CatData as IDataContainer&lt;Animal&gt;);
    • 您是否首先将列表设为List&lt;IDataContainer&lt;Animal&gt;?那应该有效
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-11
    • 1970-01-01
    • 2012-02-05
    • 2018-09-17
    相关资源
    最近更新 更多