我有两个商务合同类:行动代表,泛型,协方差和逆变
public BusinessContract
public Person : BusinessContract
在另一大类,我有以下代码:
private Action<BusinessContract> _foo;
public void Foo<T>(Action<T> bar) where T : BusinessContract
{
_foo = bar;
}
上面甚至不会编译,这让我有些困惑。我将T约束为BusinessContract,为什么编译器不知道bar可以分配给_foo?
在试图解决这个问题,我们试图将其更改为以下:
public void Foo<T>(Action<T> bar) where T : BusinessContract
{
_foo = (Action<BusinessContract>)bar;
}
现在,编译器是幸福的,所以我在其他地方写下面的代码在我的应用程序:
Foo<Person>(p => p.Name = "Joe");
运行时应用程序爆发InvalidCastException。
我不明白。我应该不能将更具体的类型转换为不太特定的类型并分配它?
UPDATE
乔恩回答了这个问题,从而得到了该点头,只是收在这个循环中,这里是我们如何最终解决问题。
private Action<BusinessContract> _foo;
public void Foo<T>(Action<T> bar) where T : BusinessContract
{
_foo = contract => bar((T)contract);
}
我们为什么要这样做?我们有一个假的DAL,我们用于单元测试。使用其中一种方法,我们需要给测试开发人员指定在测试过程中调用方法时应该执行的操作(它是从数据库更新缓存对象的刷新方法)。 Foo的目的是设置在刷新被调用时应该发生的事情。 IOW,在这个课程的其他地方,我们有以下内容。
public void Refresh(BusinessContract contract)
{
if(_foo != null)
{
_foo(contract);
}
}
例如,测试开发人员可以决定当调用Refresh时他们想要将名称设置为不同的值。
Foo<Person>(p => p.Name = "New Name");
@MDeSchaepmeester:不,我不是 - 在工作代码中(后半部分),我将一个'Action
你是对的,愚蠢的错误,我没有真正读过这段代码,并假定你用_foo作为参数调用Foo(我来这里是因为我在做* *) – MarioDS