.net 委托和接口的逆变和协变泛型类型实参

委托的每个泛型参数都可标记为协变量或者逆变量。利用这个功能,可将泛型委托类型的一个变量转型为同一个委托类型的另一个变量,后者的泛型参数类型不同。泛型类型参数可以是以下任何一种形式。
1,不变量(invariant) 意味着泛型类型参数不能更改。
2,逆变量(contravariant)意味着泛型类型参数可以从一个基类型更改为该类的派生类。在C#中,用in关键字标记逆变量形式的泛型类型参数。逆变量泛型类型参数只出现在输入位置,比如作为方法的参数。
3,协变量(covariant)意味着泛型类型参数可以从一个派生类型更改为它的基类。在C#中,是用out关键字标记协变量形式的泛型类型参数。协变量泛型类型参数只能出现在输出位置。比如作为方法的返回类型。

例如,假定存在以下委托类型定义

public delegate TResult Fun<in T, out TResult>(T arg)

其中,泛型类型参数T用in关键字标记,这使它成为一个逆变量;泛型类型参数TResult 则用out关键字标记,这使它成为一个协变量。

所以,如果像下面这样声明一个变量:

Func<Object, ArgumentException> fn1 = null

就可将它转型为另一个泛型类型参数不同的Func类型:

Func<String, Exception> fn2= fn1; //这里不需要显式转型
Exception e =fn2("");

上述代码的意思是说:fn1变量引用一个方法,该方法获取一个Object , 返回一个ArgumentException . 而fn2 变量引用另一个方法,该方法获取一个String, 返回一个Exception 。由于可以将一个String传给期待着一个Object的方法(因为String从Object派生),而且由于可以获取“返回ArgumentException的一个方法”的结果,并将这个结果视为一个Exception(因为Exception是ArgumentException的基类),所以上述代码能正常编译,而且编译时能维持编译安全性。

使用要获取泛型参数和返回值的委托时,建议尽量为逆变性和协变性指定in和out关键字。这样做不会有不良反应,并使你的委托能在更多地情形中使用。

和委托相似,具有泛型参数的接口也可将它的类型参数标记为逆变量和协变量。下面的示例接口有一个协变量泛型类型参数:

public interface IEnumerator<out T> : IEnumberator {
	Boolean MoveNext();
	T Current {get;}
}

由于T是协变量,所以一下代码可以顺利编译和运行:

// 这个方法接受任意引用类型的一个IEnumerable
Int32 Count(IEnumerable<Object> collection){ .... }
// 以下调用向Count传递一个IEnumerable<String>
Int32 c = Count(new []{"jason"})
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值