今天来结束第九章,聊下我们经常忽略,但是编译器会帮我们完成的"类型判断和重载决策",理解编译器如何帮我们完成,相信在写代码时会更明确,避免一些编译出错,排查的问题,让我们开发更给力。

  我们知道隐式类型的数组以及将方法组转换为委托类型都需要类型推断,但将方法组作为其它方法的参数进行转换时,会显得极其复杂,我们由浅入深,一步一步来看,编译器是如何帮我们做的一些推断。

 //定义一个泛型方法,参数分别为TInput类型和一个Func<TInput, TResult>类型的委托
public static TResult Get<TInput, TResult>(TInput input, Func<TInput, TResult> func)
{
return func(input);
}
static void Main(string[] args)
{
var a = Get("", x => int.Parse(x));
//第一个参数是字符串,所以可以推断TInput类型有到string类型的隐式转换
//则方法签名为:public static TResult Get<string, TResult>(string input, Func<string, TResult> func)
//第二个参数是一个Lambda表达式,根据返回的类型是一个int,所以可以推断TResult类型有到int类型的隐式转换
//则方法签名为:public static int Get<string, int>(string input, Func<string, int> func)
//根据上述的步骤,我们推断出了TInput和TResult类型
}

  返回类型集合

  从上述代码中,可以看到TResult类型是由Lambda表达式的返回值类型来推断的,那如果我有多个返回类型又是一种什么情况呢?请看下面的代码。

 var b = Get(, delegate (int x) {
if (x == )
{
return "";
}
else
{
return new object();
}
});
//由上可以推断出TInput类型有到int类型的隐式转换,则TInput为int
//而返回类型有两个,一个是string类型,一个是object类型,但是string类型有到object类型的隐式转换,则TResult为object类型
//编译器帮我们把所有的返回类型放入一个集合,对集合中的类型进行判断,判断是否有一个类型是可由剩余其它类型隐式转换可得,则把这个类型作为返回值的类型

  如何选择正确的重载

  如果重载具有二义性,那编译肯定是过不了的,要么强制转换某个参数以符合某个方法的签名,或者修改重载方法。从参数或者返回类型考虑,请参照下面一条:

  从任何类型"转换成它本身"被认为好于"转换成其它类型",如

 static void Debug0(int x) { }
static void Debug0(double x) { } Debug0(); //static void Debug0(int x)
Debug0(5.0); //static void Debug0(double x)
//int有到double的隐式转换,所以存在二义性,但根据int=>int是好于int=>double的,所以选择使用static void Debug0(int x)

  同理于返回类型,作用于委托或者Lambda表达式,如

 static int Debug1(Func<int> func) {
return func();
} static double Debug1(Func<double> func)
{
return func();
} Debug1(() => 1.1);
Debug1(delegate () { return 1.1; });
//根据Lambda表达式和匿名方法,Debug1(() => 1.1)和Debug1(delegate () { return 1.1; })返回的类型是double类型,则Lambda表达式和匿名方法转换成Func<double>类型的实例,调用的则是static double Debug1(Func<double> func)
Debug1(() => );
Debug1(delegate () { return ; });
//根据Lambda表达式和匿名方法,Debug1(() => 1)和Debug1(delegate () { return 1; })返回的类型是int类型,则Lambda表达式和匿名方法转换成Func<int>类型的实例,调用的则是static double Debug1(Func<int> func)

  请斧正。

17.C#类型判断和重载决策(九章9.4)的更多相关文章

  1. C#与Java对比学习:类型判断、类与接口继承、代码规范与编码习惯、常量定义

    类型判断符号: C#:object a;  if(a is int) { }  用 is 符号判断 Java:object a; if(a instanceof Integer) { } 用 inst ...

  2. 第17课 类型萃取(1)_基本的type_traits

    1. type_traits类型萃取 (1)type_traits通过定义一些结构体或类,并利用模板类特化和偏特化的能力,给类型赋予一些特性,这些特性根据类型的不同而异.在程序设计中可以使用这些tra ...

  3. python的数据结构分类,以及数字的处理函数,类型判断

    python的数据结构分类: 数值型 int:python3中都是长整形,没有大小限制,受限内存区域的大小 float:只有双精度型 complex:实数和虚数部分都是浮点型,1+1.2J bool: ...

  4. JS类型判断typeof PK {}.toString.call(obj)

    参考链接:https://www.talkingcoder.com/article/6333557442705696719 先看typeof <!doctype html> <htm ...

  5. Lambda03 方法引用、类型判断、变量引用

    1 方法引用 1.1 方法引用的好处 方法引用结合 Lambda 可以引用已存在的方法,省略很多编码,而且可读性更强,它可以自动装配参数与返回值. 在编写lambda表达式的时候可以通过方法引用的方式 ...

  6. Swift4 类与继承, 类型转换, 类型判断

    创建: 2018/03/05 完成: 2018/03/07 更新: 2018/03/09 完善标题 [Swift4 类与继承, 类型转换] -> [Swift4 类与继承, 类型转换与判断] 补 ...

  7. C#保留2位小数几种场景总结 游标遍历所有数据库循环执行修改数据库的sql命令 原生js轮盘抽奖实例分析(幸运大转盘抽奖) javascript中的typeof和类型判断

    C#保留2位小数几种场景总结   场景1: C#保留2位小数,.ToString("f2")确实可以,但是如果这个数字本来就小数点后面三位比如1.253,那么转化之后就会变成1.2 ...

  8. 【C/C++开发】C++11的模板类型判断——std::is_same和std::decay

    C++11的模板类型判断--std::is_same和std::decay 问题提出:有一个模板函数,函数在处理int型和double型时需要进行特殊的处理,那么怎么在编译期知道传入的参数的数据类型是 ...

  9. 20190908 On Java8 第十九章 类型信息

    第十九章 类型信息 RTTI(RunTime Type Information,运行时类型信息)能够在程序运行时发现和使用类型信息. Java 主要有两种方式在运行时识别对象和类信息: "传 ...

随机推荐

  1. hyper-v无线网络上外网

    这个通过无线网络上外网也是找了很多文章,大部分写的都不详细,没有办法成功,原理就是创建一个虚拟网卡,然后把创建的虚拟网卡和无线网卡桥接,虚拟机中使用创建的虚拟网卡,这里创建的虚拟网卡指的是用hyper ...

  2. POJ 2406 Power Strings (KMP)

    Power Strings Time Limit: 3000MSMemory Limit: 65536K Total Submissions: 29663Accepted: 12387 Descrip ...

  3. [瞎JB写] C++多态

    似乎只能通过引用或者指针进行动态多态...蛋疼的语法 #include <iostream> #include <vector> #include <memory> ...

  4. redis 一二事 - 搭建集群缓存服务器

    在如今并发的环境下,对大数据量的查询采用缓存是最好不过的了,本文使用redis搭建集群 (个人喜欢redis,对memcache不感冒) redis是3.0后增加的集群功能,非常强大 集群中应该至少有 ...

  5. Spring 一二事(5) - 依赖注入

    <!-- 依赖注入的装配过程 --> <bean id="person" class="com.lee.spring007.di.xml.setter. ...

  6. 关联:objc_getAssociatedObject和objc_setAssociatedObject使用

    为UIButton的category添加属性 UIButton+subTitle.h #import <UIKit/UIKit.h> #import <objc/runtime.h& ...

  7. 浅析CSS——元素重叠及position定位的z-index顺序

    多次在项目中遇到html页面元素的非期待重叠错误,多数还是position定位情况下z-index的问题.其实每次解决类似问题思路大致都是一样的,说到底还是对z-index的理解比较模糊,可以解决问题 ...

  8. Android studio导入eclipse项目混淆打包出错

    将proguard-android.txt复制一份重命名成proguard-rules.pro,且在build.gradle添加 release {             minifyEnabled ...

  9. zabbix一件漂亮的外衣配置

    http://www.cnblogs.com/yyhh/archive/2015/09/08/4792830.html

  10. Web 服务编程,REST 与 SOAP(转)

    原文地址:Web 服务编程,REST 与 SOAP REST 简介 在开始我们的正式讨论之前,让我们简单看一下 REST 的定义. REST(Representational State Transf ...