假设我有这样的安排:
public interface ICreatable
{
int CreatedByUserId { get; set; }
}
public class Unicorn : ICreatable
{
public int CreatedByUserId { get; set; }
}
public interface ICrudService<T>
where T : class, ICreatable
{
T DoSomething(T t);
}
public class UnicornService : ICrudService<Unicorn>
{
public Unicorn DoSomething(Unicorn unicorn)
{
var createdByUserId = unicorn.CreatedByUserId;
// ...
return unicorn;
}
}
并像这样使用它:
static void Main(string[] args)
{
var unicorn = new Unicorn();
var unicornService = new UnicornService();
unicornService.DoSomething(unicorn);
}
这运行良好。但是,假设我想将unicornService
它的接口类型及其ICrudService
泛型类型转换为它的接口类型,如下所示:
var crudService = unicornService as ICrudService<ICreatable>;
我遇到了问题。这是它的外观:
unicornService as ICrudService<Unicorn> --> casts is fine
unicornService as ICrudService<ICreatable> --> casts to null
似乎因为Unicorn
源自ICreatable
并且因为ICrudService<T> where T: class, ICreatable
它应该没有问题解决这个问题。我的搜索开始引导我进入协变和逆变,但我在那个级别迷路了。
我怎样才能crudService
投到ICrudService<ICreatable>
?
更新:
像这样使用协方差:
public interface ICrudService<out T>
然后让智能感知说“无效的方差:类型参数 'T' 必须在 'ICrudService.DoSomething(T)' 上逆变有效。'T' 是协变的。” 这是如何运作的?