我正在研究一些协变性/逆变性的东西,我有一个更广泛的问题,但归根结底都是这个问题:
GenericRepository<BaseEntity> repo = new GenericRepository<ProductStyle>(context);
尽管BaseEntity是ProductStyle的父抽象类,但这并不起作用,有没有实现此目标的方法?
out
泛型限制(这将使保存对象变得困难,但检索它们很容易),在一个接口
上(而不是类
)。 如果您有:interface IGenericRepository<out T> {...}
假如一个 IGenericRepository<ProductStyle>
可以赋值给一个类型为 IGenericRepository<BaseEntity>
的变量,因为所有的 ProductStyle
也是 BaseEntity
,而且我们限制了自己只使用协变 / out
:
IGenericRepository<BaseEntity> tmp = GetRepo<ProductStyle>(context);
// note that the right-hand-side returns IGenericRepository<ProductStyle>
...
private IGenericRepository<T> GetRepo(...) {...}
out
用法使得像以下这样的事情变得不可能:interface IGenericRepository<out T>
{
T Get(int id); // this is fine, but:
void Save(T value); // does not compile; this is not covariantly valid
}
<out T>
泛型参数。我想不到那个。有趣。 - David Hoerster我只是想知道类似这样的东西是否也有用——在定义GenericRepository时使用限制,限制T
可以是哪种基础类型:
void Main()
{
var repo = new GenericRepository<ProductStyle>(new ProductStyle());
Console.WriteLine(repo.ToString()); //just output something to make sure it works...
}
// Define other methods and classes here
public class GenericRepository<T> where T : BaseEntity {
private readonly T _inst;
public GenericRepository(T inst){
_inst = inst;
_inst.DoSomething();
}
}
public class BaseEntity {
public Int32 Id {get;set;}
public virtual void DoSomething() { Console.WriteLine("Hello"); }
}
public class ProductStyle : BaseEntity {
}
所以如果你有一个 GetRepo<T>
方法,该方法可以返回一个 T 类型的 GenericRepository,并且你可以确保 T
是 BaseEntity
的子类。
GenericRepository<ProductStyle>
没有GenericRepository<BaseEntity>
作为(直接或间接)基类,因此上述声明是非法的。你需要的是协变性。但在C#中(至少到当前版本5.0),只有泛型接口和泛型委托类型可以被协变。像你所拥有的泛型类或泛型结构体则不行。因此,你能做到的最接近的方法是创建一个接口IGenericRepository<out TEntity>
,其中out
修饰符使得接口对TEntity
具有协变性。然后你可以这样说:IGenericRepository<BaseEntity> repo = ...;
(注意I
)。 - Jeppe Stig Nielsen