已经是C#3.5的时代了,但该打的基础还是应该打牢。让我们从C#2.0开始......
注:本文所有代码均来自MSDN,笔者仅仅是在里面添加部分注释。

1.泛型

(1)基本概念和用法  
  所谓泛型,就是以类型为参数。一般是类库设计者使用泛型来设计一些通用类型(特别是集合类),而类库使用者(或称客户端代码)在使用类库的时候传入实际的类型。所以,客户端代码的类型是编译期被定下来的,比起那些纯的通用类型(如.net中的ArrayList类),不仅提高了效率(无论是装箱、拆箱,还是强制类型转换,都是需要资源的),而且增加了编译期类型检查的好处。下面两段代码体现了这种区别:


在使用泛型的时候,泛型列表应紧跟泛型的修饰类型(class,struct,delegate,method,interface等),不管是类库还是客户端代码都是如此:
public interface ISessionChannel<TSession> { /*...*/ }
public delegate TOutput Converter<TInput, TOutput>(TInput from);
public class List<T> { /*...*/ }

(2)对类型参数的约束(即泛型应用中where关键字的作用)
  如果我们不对泛型类型参数进行约束,那它在被客户端代码使用的时候,可以是任意一个clr能识别的类型。但很多时候,作为类库开发者,我们希望对类型本身作出限制,比如说我们希望这个类型是某个类型的子类,或者说我们希望它是一个值类型。这个时候我们就要用到where关键字了,如下:
public class GenericList<T> where T : CustomClass{}
CustomClass是一个我们自定义的引用类型,这里就约束了T必须为CustomClass的子类。
关于约束,还要注意一点就是它是可以叠加的,也就是说,你可以多个不互斥约束加到某一个类型身上:
class Stack<T> where T : System.IComparable<T>, IEnumerable<T>{}

(3)其他
  和泛型有关的其他一些重要概念包括:
I.泛型和反射的关系:因为公共语言运行库 (CLR) 能够在运行时访问泛型类型信息,所以可以使用反射获取关于泛型类型的信息,方法与用于非泛型类型的方法相同。
II.泛型委托的使用
III.运行库中的泛型:什么时候使用泛型类型的专用版本
这里就不一一赘述了。

2.迭代器

  可能我们很多人都用过迭代器(如果您用过foreach关键字,那您就用过用迭代器实现的类库),但可能没有自己设计过迭代器(设计一个类,让类的使用者可能通过foreach关键字来遍历类中的数据集合)。下面是从MSDN上摘下的一个简单的使用迭代器的例子:

C#2.0中主要的语法新特性// Declare the collection:
C#2.0中主要的语法新特性
public class SampleCollection
}
在这里,大家可能都会对SampleCollection.BuildCollection()方法感到有些疑惑,不仅是里面的看起来有些生疏的yeild关键字,特别是这个方法从表面上看根本没有返回任何值,应该无法通过编译才对。想搞明白这些,只能去看编译器生成的IL代码了。下面是一个ildasm返回结果的截图,我们可以看到编译期自动为我们生成了一个迭代器类型<BuilderCollection>d_0,它是一个IEnumerator:
C#2.0中主要的语法新特性
而BuildCollection()方法正是返回这样一个迭代器:
C#2.0中主要的语法新特性.method public hidebysig instance class [mscorlib]System.Collections.IEnumerable 
C#2.0中主要的语法新特性        BuildCollection() cil managed
C#2.0中主要的语法新特性{
C#2.0中主要的语法新特性  // 代码大小       
21 (0x15)
C#2.0中主要的语法新特性  .maxstack  
2
C#2.0中主要的语法新特性  .locals init (class flier.SampleCollection/'<BuildCollection>d__0' V_0
,
C#2.0中主要的语法新特性           class 
[mscorlib]System.Collections.IEnumerable V_1)
C#2.0中主要的语法新特性  IL_0000:  ldc.i4.s   -
2
C#2.0中主要的语法新特性                       //在这里构造了一个迭代器类型
C#2.0中主要的语法新特性  IL_0002:  newobj     instance void flier.SampleCollection/'<BuildCollection>d__0'::.ctor(int32)
C#2.0中主要的语法新特性  IL_0007:  stloc
.0
C#2.0中主要的语法新特性  IL_0008:  ldloc
.0
C#2.0中主要的语法新特性  IL_0009:  ldarg
.0
C#2.0中主要的语法新特性  IL_000a:  stfld      class flier.SampleCollection flier.SampleCollection/'<BuildCollection>d__0'::'<>4__this'
C#2.0中主要的语法新特性  IL_000f:  ldloc
.0
C#2.0中主要的语法新特性  IL_0010:  stloc
.1
C#2.0中主要的语法新特性  IL_0011:  br.s       IL_0013
C#2.0中主要的语法新特性  IL_0013:  ldloc
.1
C#2.0中主要的语法新特性  IL_0014:  ret
C#2.0中主要的语法新特性} // end of method SampleCollection::BuildCollection

而上面编译器所做的一切工作,都是由yield关键字指定的。

3.可空类型

  可空类型允许我们为布尔、整数等值类型附上Null值,这在有些编程环境下会非常有用(例如,数据库中的布尔型字段可以存储值 true 或 false,或者,该字段也可以未定义)。下面是MSDN上的一个关于可空类型的小例子:

C#2.0中主要的语法新特性class NullableExample
}

4.匿名方法

  它的概念和用法都比较简单,就是把一个代码块直接传递给一个委托的语法形式,如下例所示:

C#2.0中主要的语法新特性// Declare a delegate
C#2.0中主要的语法新特性
delegate void Printer(string s);
C#2.0中主要的语法新特性
C#2.0中主要的语法新特性
class TestClass
}

5.名字空间别名限定符
   这个限定符的用法为"A::B",其中左边A是一个名字空间的别名,B是一个当前要使用的类型名称,整个合在一起就是指定去A下面查找B。很显然,这个限定符用于多个名字空间下定义了相同类型名的情况。其中A有一个系统已经定义的别名global,指代全局名字空间。下面是一个例子:
C#2.0中主要的语法新特性using System;
C#2.0中主要的语法新特性
class TestApp
}

当然,除了global,你也可以自己定义一些名字空间别名,这里就不多举例了。

6.委托中的类型相容性(协变与逆变)
  这其实是一种让我们在一些合法隐式转换的帮助下,把返回值具有类属关系的代理和传入参数具有类属关系的代理进行合并的一种方法,前者被称为“协变”,后者被称为“逆变”。
(1)协变

C#2.0中主要的语法新特性class Mammals
}

(2)逆变
C#2.0中主要的语法新特性System.DateTime lastActivity;
C#2.0中主要的语法新特性
public Form1()
}

相关文章:

  • 2021-10-30
  • 2022-12-23
  • 2022-12-23
  • 2021-07-01
  • 2021-06-02
  • 2021-11-22
  • 2021-08-23
  • 2021-06-05
猜你喜欢
  • 2021-07-30
  • 2022-12-23
  • 2021-07-30
  • 2021-12-12
  • 2022-12-23
  • 2021-07-05
  • 2021-06-01
相关资源
相似解决方案