c# in depth 之泛型实参的类型推断
调用泛型方法时,指定类型实参常常会显得很多余。为简化工作,c#2编译器被赋予了一定的“智能”,让你在调用方法时,不需要显式声明类型实参。
在深入讨论这个主题之前,必须强调一下:类型推断只适用于泛型方法,不适用于泛型类型。
例子:static List<T> MakeList<T>(T first,T second)
...
List<String> list=MakeList<string>("Line1","Line2");
方法中的每个参数都声明为类型T。即使拿掉方法中调用表达式的<string>部分,也很容易看出在调用方法时,为T使用的类型实参是string。编译器允许将其省略,变成:
List<string> list=MakeList("Line2","Line2");
使用类型推断并非总是意味着增加了可读性。某些情况下会造成读者更难判断你要使用什么类型实参-即使编译器能轻松地判断出来。建议具体情况具体分析。在推断可用的时候,让编译器推断类型实参,多数情况下都没有问题。
注意,编译器之所以能够确定我们要将string作为类型实参使用,是因为对list的赋值也在起作用,它也指定了并且必须指定类型实参。然而,假如编译器推断错了你想要使用的类型实参,你仍可能得到一个编译错误。
编译器为什么会弄错呢?假定实际想用object作为类型实参。我们传递的方法实参仍是有效的,编译器认为我们想要的是string,因为传递的两个参数都是字符串。修改其中一个实参,把它显示转换为object,类型推断就会失败。因为一个方法实参指出T应该是string,另一个指出T应该是一个object。此时,编译器会考虑这种情况并且告知用户将T设为object能满足一切情况,将T设为string则不能。但是,在c#语言规范中,只提供了有限的推断步骤。其基本步骤如下:
1.针对每一个方法实参(普通圆括号中的参数,而不是尖括号中的),都尝试推断出泛型方法的一些类型实参。这一步是相当简单的技术
2.验证步骤一的所有结果都是一致的—换言之,假如从一个方法实参中推断出了某类型参数的类型实参,但根据另外一个类型实参推断出同一个类型参数具有另一个类型实参,则此次方法调用的推断失败。
3.验证泛型方法需要的所有类型实参都已被推断出来,不能让编译器推断一部分,自己显式指定另一部分。要么全部推断,要么全部指定。
类型推断可以结合基于类型参数数量的类型名称重载的想法,来简化泛型类型的使用。
程序清单:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace 类型推断
{
class Program
{
public static List<T> MakeList<T>(T f, T s)
{
List<T> list = new List<T>();
list.Add(f);
list.Add(s);
return list;
}
static void Main(string[] args)
{
List<object> list = MakeList("", (object)"");
foreach (string s in list)
{
Console.WriteLine(s);
}
}
}
}
运行结果:

试验知:类型推断中,如果类型如object,至少要强制转换类型实参中的一个参数,否则推断失败。
c# in depth 之泛型实参的类型推断的更多相关文章
- Java 8新特性探究(三)泛型的目标类型推断
简单理解泛型 泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数.通俗点将就是"类型的变量".这种类型变量可以用在类.接口和方法 ...
- [Effective Modern C++] Item 1. Understand template type deduction - 了解模板类型推断
条款一 了解模板类型推断 基本情况 首先定义函数模板和函数调用的形式如下,在编译期间,编译器推断T和ParamType的类型,两者基本不相同,因为ParamType常常包含const.引用等修饰符 t ...
- Java 10 实战第 1 篇:局部变量类型推断
现在 Java 9 被遗弃了直接升级到了 Java 10,之前也发过 Java 10 新特性的文章,现在是开始实战 Java 10 的时候了. 今天要实战的是 Java 10 中最重要的特性:局部变量 ...
- <T>泛型,广泛的类型
其实早在1999年的JSR 14规范中就提到了泛型概念,知道jdk5泛型的使用才正式发布,在jdk7后,又对泛型做了优化,泛型的推断. 泛型类 public class Pair<T> { ...
- 泛型T的类型获取
T.getClass()或者T.class都是非法的,因为T是泛型变量. 由于一个类的类型是什么是在编译期处理的,故不能在运行时直接在Base里得到T的实际类型. /** * 可以在service层直 ...
- 使用C#反射中的MakeGenericType函数,来为泛型方法和泛型类指定(泛型的)类型
C#反射中的MakeGenericType函数可以用来指定泛型方法和泛型类的具体类型,方法如下面代码所示这里就不多讲了,详情看下面代码一切就清楚了: using System; using Syste ...
- Java泛型-内部原理: 类型擦除以及类型擦除带来的问题
一:Java泛型的实现方法:类型擦除 大家都知道,Java的泛型是伪泛型,这是因为Java在编译期间,所有的泛型信息都会被擦掉,正确理解泛型概念的首要前提是理解类型擦除.Java的泛型基本上都是在编译 ...
- C# 泛型多种参数类型与多重约束 示例
C# 泛型多种参数类型与多重约束 示例 interface IMyInterface { } class Dictionary<TKey, TVal> where TKey : IComp ...
- Gson通过借助TypeToken获取泛型参数的类型的方法
最近在使用Google的Gson包进行Json和Java对象之间的转化,对于包含泛型的类的序列化和反序列化Gson也提供了很好的支持,感觉有点意思,就花时间研究了一下. 由于Java泛型的实现机制,使 ...
随机推荐
- ubuntu下配置qt+opengl+opencv
原地址:http://www.cnblogs.com/aleny-liu/archive/2011/12/16/aleny-Qtnote1.html http://blog.csdn.net/jdh9 ...
- Jquery学习笔记:操作form表单元素之一(文本框和下拉框)
一.概述 在web页面开发中,经常需要获取和设置表单元素的值(如文本框中的内容),特别是在ajax应用中,更是常态.本文系统的介绍下如何操作. 同操作其它html元素一样,操作的过程差不多. 第一步, ...
- 相邻数字的基数等比确定进制问题pojg2972
解决数制转换问题时,如果所给的数值不是用十进制表示的,一般用一个字符型数组来存放,数组的每个元素分别存储它的一位数字.然后按位转换求和,得到十进制表示,再把十进制转成成其他所求的进制表示.转成的结果也 ...
- 简单的http代理服务器
简单的http代理服务器 本项目课程是基于 Python 实现的一个简单的 HTTP 代理服务器,要求用户需了解 Python 基础和一定的 HTTP 服务器基础知识.
- Connection reset by peer问题分析
extremetable导出excel,弹出一个下载窗口,这时不点下载而点取消,则报下面的异常: ClientAbortException Caused by: java.net.SocketExce ...
- jquery validate 插件使用小结
项目中整合了jquery validate插件,仿照别人的使用写了我的表单验证,结果不起作用.然后就各种找原因. 在网上下了jquery validate插件的完整包,看了看里边的例子,跟我的使用貌似 ...
- Android 代码混淆
什么是代码混淆 Java 是一种跨平台的.解释型语言,Java 源代码编译成中间”字节码”存储于 class 文件中.由于跨平台的需要,Java 字节码中包括了很多源代码信息,如变量名.方法名,并且通 ...
- Unity3d 帧率设置 及在游戏执行时显示帧率
在Unity3d 中能够通过代码设置 来限定游戏帧率. Application.targetFrameRate=-1; 设置为 -1 表示不限定帧率. 转自http://blog.csdn.net/h ...
- C语言,C++,static
术语static有着不寻常的历史.起初,在C中引入关键字static是为了表示退出一个块后仍然存在的局部变量.随后,static在C中有了第二种含义:用来表示不能被其它文件访问的全局变量和函数.为了避 ...
- AsyncTask的用法总结
这几天被AsyncTask虐得不行,在此总结下 首先: AsyncTask的参数介绍 在开发Android移动客户端的时候往往要使用多线程来进行操作,我们通常会将耗时的操作放在单独的线程执行,避免其占 ...