第十章 扩展方法
看NutShell
第十一章 查询表达式和LINQ to Objects
看NutShell
第十二章 超越集合的LINQ
简化代码的微小修改
第十三章
可选参数和命名实参
1.可选参数,需要给定一个默认值
2.默认值也可以指定为null
3.命名实参:在参数调用的时候写上参数的命名,可以打乱参数的顺序
4.命名实参和位置实参可以混用,位置实参必须在最前面
5.当参数是一个表达式的时候,会先全部计算好所有参数表达式的值,然后再允许本方法。函数表达式参数的计算顺序是从左到右的
6.命名参数和可选参数结合
static void Main(string[] args)
{
//b是默认的1
Foo("zan", c: "bean");
Console.ReadLine();
}
static void Foo(string a,int b = 1, string c = "fff")
{
}
7.命名参数和可选参数可以有效减少重载的数量
改善COM互操作性
接口和委托的泛型可变性
协变性和逆变性
1.协变性:用于向调用者返回某项操作的值,(由子类向基类转化)
2.逆变性:传入API的值,(由基类向子类转化)
3.不变性:双向传递的值
4.协变和逆变只能使用在泛型的接口和委托中
5.尽量不自定义out和in,只使用.net框架提供的协变和逆变功能
对锁和字段风格的事件的微笑改变
健壮的锁
对于lock代码,编译器会帮我们默认的生成一些别的代码,C# 4更好的解决了这个问题。确保锁的释放,或者说应该被释放的时候才释放,不需要释放的时候不需要释放
字段风格的事件
事件不显示的包含add和remove方法,和属性一样,在后台创建一个field。
静态语言中动态绑定
何谓、何时、为何、如何
1.绑定:决定使用哪个成员的过程
2.静态类型:绑定发生在编译时
3.动态类型:绑定发生在编译时。编译器可以检查语法是否正确,但是无法检查使用的方法或属性是否真的存在
动态类型什么时候用,为什么
1.知道要调用的成员名称,要传入的参数,要调用的对象
2.所调用对象的类型和参数的类型
3.对象可以通过分析提供给他的名称和参数来响应某个调用
如何提供动态类型
1.使用dynamic
2.事实上,dynamic并不代表一个特定的CLR类型。它实际上只是包含DynamicAttribute特性的Object类型。但是可以将其视为一个真正的类型
关于动态的快速指南
1.特点:
几乎所有的CLR类型都可以隐式转换为dynamic类型
所有dynamic类型都可以转为CLR类型
使用dynamic类型的表达式通常会动态的求值
动态求值的表达式的静态类型通常被视为dynamic
动态类型示例
COM和Office
动态语言
可以和动态语言进行交互,Python
纯托管代码中的动态类型
1.执行时类型推断
2.弥补泛型操作符的不足
3.鸭子类型
知道在执行时一定有固定的成员,但是无法确定这个成员,因为所有符合这个基类的子类都有这个成员(但是不一定定义在基类中)。可以使用动态类型来调用
4.多重分发
对于静态类型,C#使用单一分发,有函数重载的情况下,在编译时就确定了唯一的一种,在执行时就会执行哪一种。
多重分发,有重载的情况,在执行时才会确定使用哪一种类型
static int Count<T>(ICollection<T> collection)
{
return collection.Count;
}
static int Count(ICollection collection)
{
return collection.Count;
}
static int Count(string collection)
{
return collection.Length;
}
static int Count(IEnumerable collection)
{
int count = 0;
foreach (object item in collection)
{
count++;
}
return count;
}
static void Print(IEnumerable collection)
{
dynamic d = collection;
int count = Count(d);
Console.WriteLine(count);
}
幕后原理
DLR简介
1.DLR:动态语言运行时
2.DLR:动态语言运行时是所有动态语言和C#编译器用来动态执行代码的库
3.DLR将用绑定器、调用点、元对象,以及各种概念表示的代码转换为表达式树,后者可以被编译为IL,并最终由CLR编译为本地代码。
DLR核心概念
1.目的:基于执行时才能知道的信息以高级形式表示并执行代码
2.调用点:调用方法的地方
3.绑定器:取决于调用的语言,并且是调用的一部分
4.接收器:动态类型所引用的对象
5.规则:如何执行一个调用所作出的决策。调用点表现为这种行为时所处的环境以及行为本身
6.缓存
C# 编译器如何处理动态
1.如果使用了动态,那么它就是动态的。如果方法有重载,那么dynamic参数不一定会被使用
2.除了在方法内部以外,dynamic类型的参数将被视为object类型,也确实是object类型
2.CLR类型和动态类型之间的转换
3.动态表达式并不总是动态求值的
实现动态行为
ExpandObject和DynamicObject
参考C# Nut Shell