这个问题是我在测试上一篇随笔《C# 使用 Binder 类自定义反射》中的类时发现的,当时为了能够让 PowerBinder 支持泛型方法绑定,完成了一些简单的类型推断工作,但是它只能支持直接使用泛型参数 T 作为参数类型,对于 T[],IList
创新互联建站专注于三门企业网站建设,成都响应式网站建设公司,商城网站开发。三门网站建设公司,为三门等地区提供建站服务。全流程按需网站制作,专业设计,全程项目跟踪,创新互联建站专业和态度为您提供的服务
或者举个复杂点的例子,对于下面的泛型方法定义:
- 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
对于相应的封闭泛型方法的调用 Method
泛型方法的类型推断,从形式上来定义,就是对给定泛型方法 Tr 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 进行下限推断:
2. 精确推断
这里的精确推断指的是对于给定的实参类型 U,找到合适的形参类型 V,使得 U == V。
按如下所述从类型 U 到类型 V 进行精确推断:
如果存在以上任意情况,则从每个 Ui 到对应的 Vi 进行精确推断。
3. 上限推断
这里的上限推断指的是对于给定的实参类型 U,找到合适的形参类型 V,使得 U.IsImplicitFrom(V)。
按如下所述从类型 U 到类型 V 进行上限推断:
的推断。也不进行从 U1 到 X或 Y的推断。),则从每个 Ui 到对应的 Vi 进行推断,推断依赖于 C 的第 i 个类型参数:
- 如果该参数是协变的,则进行上限推断。
- 如果该参数是逆变的,则进行下限推断。
- 如果该参数是固定的,则进行精确推断。
4. 固定
固定是为了根据之前的算法得到的界限集,推断出类型参数的合适的值。
具有界限集的类型变量 Xi 按如下方式固定:
以上就是泛型方法的类型推断算法,其中只考虑了方法实参和方法形参一一对应的情况,如果需要处理 params T[] 参数,则需要对最后一个参数进行特殊处理,并分别使用 T 和 T[] 进行一次类型推断。做两次类型推断,就是为了判断是否是方法的展开形式的调用。
或者说,对于泛型方法定义
- void Method
(T a, params T[] args);
如果参数为 { typeof(int), typeof(int[]) } 和 { typeof(nt[]), typeof(int[]) },虽然 T[] 对应的实参是相同的,但推断出的 T 却是不同的,这就需要利用两次类型推断来处理。
这个算法的实现加上注释大概有 500 多行,这里就不再贴出,基本就是按照上面的 4 步来的,只是在一些细节上采用了更高效的做法。所有源码可以见这里。
文章标题:C#泛型方法的类型推断
网页网址:http://www.shufengxianlan.com/qtweb/news35/215235.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联