一,委托
- 委托封装了包含特殊返回类型和一组参数的行为,类似包含单一方法接口。
- 委托类型声明中所描述的类型签名决定了哪个方法可以用于创建委托实例,同时决定了调用的签名:委托类型实际上只是参数类型的一个列表以及一个返回类型
- 创建委托实例,需要一个方法已经调用该方法的目标:
- 委托实例不易变形: 委托是不易变的。委托实例就和string一样。Delegate.Combine和string.Concat很像,都是合并现有的实例形 成一个新实例
- 每个委托实例都包含一个调用列表——一个操作列表:
委托实例还有一个调用列表与之关联,如下图:
- 委托实例可以合并到一起,也可以从委托实例中删除另一个
- 事件不是委托实例,只是成对的add/remove方法(类似属性的取值和赋值)
delegate void StringProcessor(string input);//委托签名
class Person
{
string name;
public Person(string name)
{
this.name = name;
}
public void Say(string msg)
{
Console.WriteLine("{0}agy:{1}", name, msg);
}
public void tu(string msg)
{
Console.WriteLine("{0}agy:{1}", name, msg);
}
}
#region 委托事件
Person jon = new Person("Jon");
Person tom = new Person("tom");
StringProcessor jons, toms, background;///创建委托实例
jons = new StringProcessor(jon.Say);//委托实例使用的方法
toms = new StringProcessor(tom.Say);
background = new StringProcessor(Backgroud.Note);
jons += toms;
jons("Hello,jon");
toms("Hello,tom");
background("note");
#endregion
二,类型系统特征
- C#1是静态类型的——编译器知道你能使用哪些成员:每个变量都有一个特并的类型,而且该类型在编译时是已知的,只有该类型已知的操作才被允许。
- C#1是显示的——必须告诉编译器变量具有什么类型:每个变量的类型必须在声明的时候指定。
- C#1是安全的——除非存在真实的转换关系,否则不能把一个类型当作另一个类型使用。(在完全无关的结构之间进行强制类型转换,很容易造成严重的后果)
- 静态类型不予许一个集合成为强类型的“字符串列表”或者“整数列表”,除非针对不同的元素使用大量重复代码:数组是强类型的,所以不可能将一个string[]的一个元素设置成一个FileStream,引用类型数组支持协变,只要元素类型之间允许转换。
- 方法的覆盖和实现不允许协变性/逆变性。
“协变”是指能够使用与原始指定的派生类型相比,派生程度更大的类型。
“逆变”则是指能够使用派生程度更小的类型。
只是有一点记住Dog 继承自Animal,
所以Dog变成Animal 就是和谐的变化(协变),而如果Animal 变成Dog就是不正常的变化(逆变)
三,值类型和引用类型
- 对于引用类型的表达式(变量),它的值是一个引用,而非对象:
- 引用就像URL——允许你访问真实数据的一小片数据。
- 对于值类型的表达式,它的值是实际数据。
- 引用类型的对象总是在堆上,值类型的值既可以在栈上也可能在堆上,具体取决于上下文:变量的值在它声明的位置存储,在一个类中有一个int类型的实例变量,那么这个int的值就和对象中其他数据在一起,也就是堆中。
- 引用类型的值作为方法参数使用是,参数默认是以“值传递”——但值得本身是一个引用。
- 值类型的值会在需要引用类型的行为的时候被装箱,反之,则拆箱:当一个值类型调用Tostring,Equals或GetHashCode方法时,如果该类型没有覆盖这些方法,也会发生装箱。尽量少用拆箱和装箱,当大量操作时,这会影响性能。
dynamic d = "hello";//动态类型
Console.WriteLine(d.Length);
d = new string[] { "hi", "there" };
Console.WriteLine(d.Length);