c#中的协变性与逆变性,Part Three:方法组转换的可变性

上一次我讨论了C#中的数组协变性如何会产生Bug(Java也是,还有很多其他语言)今天,我们讲讲一个C#2.0提供的健壮的可变性:从方法组到委托的转换。这是一种更复杂的可变性,所以我需要仔细地讲讲。

假设你有一个方法返回Giraffe:

static Giraffe MakeGiraffe() {...

再假设你有一个委托类型,代表一个不接受参数并返回一个Animal的函数。比如,Func,下面的隐式转换应该合法吗?

Func<Animal> func = MakeGiraffe;

func的调用者希望返回一个Animal,实际的函数总是返回Giraffe,Giraffe也是一个Animal,所以func的调用者总能获得它们想要的东西。这个隐式转换没毛病。因此,我们可以让从函数组到委托的转换的返回类型是协变的

现在假设你有两个函数,其中一个接受Giraffe参数,另一个接受Animal参数:

void Foo(Giraffe g) {}
void Bar(Animal a) {}

和一个委托,委托匹配返回void接受Mammal参数的函数。

Action<Mammal> action1 = Foo; //illegal
Action<Mammal> action2 = Bar; //legal

为什么第一个赋值是非法的?因为action1的调用者可以传递一个Tiger,但是Foo不能接受的一个Tiger,只能接受Giraffe!第二个赋值是合法的因为Bar可以接受任何Animal。

在我们前一个例子中,我们保留了可赋值性的方向( the direction of the assignability,不知道怎么翻译。。),Giraffe小于Animal,所以一个返回Giraffe的方法小于返回Animal的委托。在这个例子中我们反转了可赋值性的方向;Mammal比Animal要小,所以一个接受Animal的方法比接受一个Mammal的委托要小,因为方向被翻转了,函数组到委托的转换对于参数类型是逆变的

注意上述所说的都只适用于引用类型,我们从来不会说这样的话“每个int都可以转换为long,所以一个返回int的函数可以赋值给Func变量”。

下一次:更强的委托可变性。


是的,我之前说过可变性是基于类型的操作的属性,然后我现在有一个基于方法组的操作,在C#中和类型无关。我在写博客,不是写论文,你懂的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值