【发布时间】:2013-10-14 07:51:57
【问题描述】:
假设我有这样的安排:
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' 是协变的。”这是如何工作的?
【问题讨论】:
-
尝试使用
ICrudService<out T>并查看out 以了解它的含义。 -
谢谢@AlessandroD'Andria 我更新了这个问题。使用 out 关键字会导致另一个问题。我忽略了一些简单的事情吗?
-
您发布的代码与
out T参数一起工作正常,因此问题出在其他地方。 -
@AlessandroD'Andria 不,它没有。它使用
T作为方法的参数和返回值,这意味着它相对于T是不变的,既不能是协变的也不能是逆变的。 -
@Sevy 你说得对,我只看到编辑...
标签: c# generics interface covariance contravariance