如何将子类分配给非泛型类中的泛型字段

时间:2015-12-02 19:36:11

标签: c# generics inheritance

在C#中,我试图将私有泛型变量存储在通过泛型方法传入的非泛型类中。 泛型方法应该将子类转换为基类类型。

以下是此问题的示例:

class BaseModel { }
class DerivedModel : BaseModel { }

class Data<T> where T : BaseModel { }

// Class is NOT generic
class DataConsumer
{
    // How do I set this to generic?
    private Data<BaseModel> data;

    public void Set<T>(Data<T> data) where T : BaseModel
    {
        // Compile time error: 
        // Cannot convert source type 'Generic.Data<T> 
        // to target type 'Generic.Data<Generic.BaseModel>'
        this.data = data;
    }
}

2 个答案:

答案 0 :(得分:4)

这是因为您尝试将更多派生类型Data<T>分配给基类型Data<BaseModel>,这在通用类中是不允许的。

您有两种选择:

1-制作DataConsumer通用:

class DataConsumer<T> where T : BaseModel
{
    private Data<T> data;

    public void Set(Data<T> data)
    {
        this.data = data;
    }
}

2-或,使Data成为界面而非类,并使用T关键字将out标记为协变类型:

interface IData<out T> where T : BaseModel { }

class DataConsumer
{
    private IData<BaseModel> data;

    public void Set<T>(IData<T> data) where T : BaseModel
    {
        this.data = data;
    }
}

详细了解Covariance and Contravariance in Generics here

答案 1 :(得分:0)

this.data的类型为Data<BaseModel>,而函数参数data的类型为Data<T : BaseModel>

您的示例首先会破坏泛型的整个目的,但您可以将Set()方法声明为非泛型方法,并强制客户端执行强制转换。

private Data<BaseModel> data;

public void Set(Data<BaseModel> data)
{
  this.data = data;
}

作为旁注,如果您声明所涉及的所有实体都是通用的,那么约束只允许您通过BaseModel合同操纵对象,所以我无法看到显然演员是必要的。