北大青鸟

首页 > .Net技术教程

站内公告

C#泛型方法的类型推断

责任编辑:宏鹏来源:武汉北大青鸟鲁广校区时间:07-26
导读:北大青鸟鲁广校区老师为你讲解C#泛型方法的类型推断。 这里所谓的泛型方法的类型推断,指的是根据已有的方法实参的类型,推断出泛型方法的类型实参。例如一个泛型方法 vo

北大青鸟鲁广校区老师为你讲解C#泛型方法的类型推断。

这里所谓的“泛型方法的类型推断”,指的是根据已有的方法实参的类型,推断出泛型方法的类型实参。例如一个泛型方法 void Method(T[] args),如果我给出方法实参类型是 int[],那么希望能够推断出 T = int。

举个复杂点的例子,对于下面的泛型方法定义:

void Method(IList a, params T[] args);

再给出参数类型为:

{ typeof(IList), typeof(int[]) } { typeof(IList), typeof(int[]) } { typeof(IList), typeof(int[][]) }

我希望能够正确的推断出 T 的类型分别为 int、int[] 和 int[]。

后来参考了《CSharp Language Specification》v5.0 中 7.5.2 类型推断 一节,规范中给出了 C# 中进行类型推断的两阶段算法,算法分为两阶段主要是为了支持实参表达式和匿名函数的推断,而我的需求则要简单很多,只要支持普通的参数就可以了。又参考了 7.5.2.13 方法组转换的类型推断 一节,终得到了下面的简化算法。

先对几个名词进行区分:类型形参、类型实参、方法形参和方法实参。

对于泛型方法定义 void Method(T a),其中的 T 是类型形参,T a 是方法形参。

对于相应的封闭泛型方法的调用 Method(10),其中的 int 就是类型实参,10 就是方法实参。

泛型方法的类型推断,从形式上来定义,就是对给定泛型方法 Tr M(T1 x1, …, Tm xm),其中 Tr 是返回值,X1, …, Xn 是类型形参,T1, …, Tm 是方法形参,和一个委托类型 D(U1 x1, …, Um xm),找到一组类型实参 S1, …, Sn,使表达式 M 与 D 兼容(D 可由 M 隐式转换而来)。

该算法先认为所有 Xi 均未固定(即没有预设值),并从 D 的每个实参类型 Ui 到 M 的对应形参类型 Ti 进行下限推断(前提是 Ti 包含类型形参,即 ContainsGenericParameters == true),但是如果 xi 为 ref 或 out 形参,则从 Ui 到 Ti 进行推断。如果没有为任何 Xi 找到界限,则类型推断将失败。否则,所有将 Xi 均固定到对应的 Si,它们是类型推断的结果。下面给出详细的推断算法,这里的算法经过了我的修改,与原规范并不完相同。

1. 下限推断

这里的下限推断指的是对于给定的实参类型 U,找到合适的形参类型 V,使得 V.IsImplicitFrom(U)。

按如下所述从类型 U 到类型 V 进行下限推断:

如果 V 是 Xi 之一,则将 U 添加到 Xi 的下限界限集中。

否则,如果 V 为 V1? 类型,而 U 为 U1? 类型,则从 U1 到 V1 进行下限推断。

否则,如果 V 是数组类型 V1[…],U 是具有相同秩的数组类型 U1[…],或者 V 是一个 IEnumerable、ICollection 或 IList,U 是一维数组类型 U1[],则从 U1 到 V1 进行下限推断。

否则,如果 V 是构造类、结构、接口或委托类型 C,并且存在一类型 C ,使 U 等于、(直接或间接)继承自或者(直接或间接)实现 C(“一性”限制表示对于 interface C{} class U: C, C{},不进行从 U 到 C 的推断,因为 U1 可以是 X 或 Y。),则从每个 Ui 到对应的 Vi 进行推断,推断依赖于 C 的第 i 个类型参数:

如果该参数是协变的,则进行下限推断。

如果该参数是逆变的,则进行上限推断。

如果该参数是固定的,则进行推断。

否则,不进行任何推断。

2. 推断

这里的推断指的是对于给定的实参类型 U,找到合适的形参类型 V,使得 U == V。

按如下所述从类型 U 到类型 V 进行推断:

如果 V 是 Xi 之一,则将 U 添加到 Xi 的界限集中。

否则,通过检查是否存在以下任何一种情况来确定集合 V1…Vk 和 U1…Uk :

V 是数组类型 V1[…] , U 是具有相同秩的数组类型 U1[…]。

V 是类型 V1?,U 是类型 U1?。

V 是构造类型 C 并且 U 是构造类型 C 。

如果存在以上任意情况,则从每个 Ui 到对应的 Vi 进行推断。

否则,不进行任何推断。

3. 上限推断

这里的上限推断指的是对于给定的实参类型 U,找到合适的形参类型 V,使得 U.IsImplicitFrom(V)。

按如下所述从类型 U 到类型 V 进行上限推断:

如果 V 是 Xi 之一,则将 U 添加到 Xi 的上限界限集中。

否则,如果 V 为 V1? 类型,而 U 为 U1? 类型,则从 U1 到 V1 进行上限推断。

否则,如果 V 是数组类型 V1[…],U 是具有相同秩的数组类型 U1[…],或者 V 是一维数组类型 V1[],U 是一个 IEnumerable、ICollection 或 IList,则从 U1 到 V1 进行上限推断。

否则,如果 U 是构造类、结构、接口或委托类型 C,V 是等于、(直接或间接)继承自或者(直接或间接)实现一类型 C 的类、结构、接口或委托类型(“一性”限制表示如果我们有 interface C{} class V: C>, C>{},则不进行从 C 到 V 的推断。也不进行从 U1 到 X 或 Y 的推断。),则从每个 Ui 到对应的 Vi 进行推断,推断依赖于 C 的第 i 个类型参数:

如果该参数是协变的,则进行上限推断。

如果该参数是逆变的,则进行下限推断。

如果该参数是固定的,则进行推断。

否则,不进行任何推断。

4. 固定

固定是为了根据之前的算法得到的界限集,推断出类型参数的合适的值。

具有界限集的类型变量 Xi 按如下方式固定:

候选类型集 Ui 是在 Xi 的界限集中的所有类型的集合。

然后我们依次检查 Xi 的每个界限:对于 Xi 的每个界限 U,将与 U 不同的所有类型 Ui 都从候选集中移除(要求 U == Ui)。对于 Xi 的每个下限 U,将不存在从 U 进行的隐式转换的所有类型 Ui 都从候选集中移除(要求 Ui.IsImplicitFrom(U))。对于 Xi 的每个上限 U,将不存在从其到 U 进行的隐式转换的所有类型 Ui 都从候选集中移除(要求 U.IsImplicitFrom(Ui))。

如果在剩下的候选类型 Ui 中,存在一类型 V,该类型可由其他所有候选类型经隐式转换而来,则将 Xi 固定到 V(也就是说,要求 V 是其中通用的类型)。

否则,类型推断将失败。

以上就是泛型方法的类型推断算法,其中只考虑了方法实参和方法形参一一对应的情况,如果需要处理 params T[] 参数,则需要对后一个参数进行特殊处理,并分别使用 T 和 T[] 进行一次类型推断。做两次类型推断,就是为了判断是否是方法的展开形式的调用。

或者说,对于泛型方法定义

void Method(T a, params T[] args);

如果参数为 { typeof(int), typeof(int[]) } 和 { typeof(nt[]), typeof(int[]) },虽然 T[] 对应的实参是相同的,但推断出的 T 却是不同的,这就需要利用两次类型推断来处理。

这个算法的实现加上注释大概有 500 多行,这里就不再贴出,基本就是按照上面的 4 步来的,只是在一些细节上采用了更高效的做法。

想了解更多关于北大青鸟鲁广校区Java教程及课程信息,请点击湖北北大青鸟官方网站:www.027hpedu.com 或咨询QQ:1119635923,电话:13125006136。

    看过该.Net技术教程的还看过

本文标题:C#泛型方法的类型推断,责任编辑:宏鹏,来源:武汉北大青鸟鲁广校区栏目,于07-26发布于北大青鸟鲁广校区。北大青鸟鲁广校区老师为你讲解C#泛型方法的类型推断。 这里所谓的泛型方法的类型推断,指的是根据已有的方法实参的类型,推断出泛型方法的类型实参。例如一个泛型方法 vo

专业老师指导

赵老师

赵老师

从事IT教育培训十年有余,致力于帮助广大学子找到适合自己的专业

立即在线咨询

培训咨询客服

陈老师

陈老师

IT培训专业客服,用自己的真诚解决了无数学子的困惑

立即在线咨询

本文地址:https://m.027hpedu.com/html/2810.html

文章标题:C#泛型方法的类型推断

上一篇:

下一篇:

热点关注

推荐.Net技术教程

热门.Net技术教程

初中生
高中生
大学生
打工者
男生
女生

预约你的精彩未来

预约将免费领取7天课程体验卡

-------请选择试预约课程-------

JAVA
WEB前端
PHP
UI设计
Python
电子商务
视频剪辑
大数据工程师
平面设计

83345人已领取

全国百余家校区

只为您方便就学

北大青鸟鲁广校区

北大青鸟鲁广校区

武汉市洪山区珞喻路724号(地铁二号线光谷广场站F口出)

预约到校
领取学习大礼包

首页

热门课程

视频网课

新闻资讯

关于学校

联系学校

预约选课申请

  • 预约时间

    请选择预约时间

  • 预约课程

    请选择预约课程

  • 姓   名
  • 手机号
  • QQ 号
  • 微信号

添加老师微信号

专业老师24小时1对1学习指导

定制专属于你的专属学习方案

微信号:17740513250

复制老师的微信号

复制成功啦

快去微信添加老师为好友吧~

北大青鸟小青

微信号:17740513250

北大青鸟小青

微信号:17740513250

设置备注
小主知道啦