在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;
}
}
这是因为您试图将更派生的类型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-OR,使Data
成为接口而不是类,并使用out
关键字将T
标记为协变类型:
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;
}
}
阅读更多关于Generics中协方差和反方差的信息,点击此处
this.data
属于Data<BaseModel>
类型,而函数参数data
属于Data<T : BaseModel>
类型。
您的示例一开始就有点违背了泛型的全部目的,但您可以将Set()
方法声明为非泛型方法,并强制客户端执行强制转换。
private Data<BaseModel> data;
public void Set(Data<BaseModel> data)
{
this.data = data;
}
顺便说一句,如果您声明所有涉及的实体都是泛型的,那么约束将只允许您通过BaseModel
的契约来操作对象,所以我看不出显式强制转换是必要的。