hebutyll 发表于 2013-3-12 15:33:07

C#语言学习:泛型(Generics)

   之前写过在代码模块发了关于扩展方法以及排序算法的帖子,本来想在这两方面写的更为详细一些,不过后来想了想,还是从C#的语言基础来写起吧。基本思路参考的是《Professional.Csharp.4.and.DotNet.4》这本书。因为这本书看了有几遍了,对于里面的内容更了解一些。关于类,接口,继承这些比较基本的知识就不写了,打算从我认为的第一个难点:泛型开始写起。OK,进入正题。
   泛型是在.net 2.0中出现的,并且作为基本语法集成在CLR中,所以不仅C#中存在泛型,包括VB.NET,visual C++.NET都可以使用泛型。.NET中的泛型和C++中的模板是类似的,至少在语法表现上。
    1. 为什么要使用泛型?
      在.NET 2.0之前并没有泛型这个概念。当时如果需要动态存储数据的话,只能是把把所有的数据都放在一个ArrayList里面。而   ArrayList会将所有类型(值类型,引用类型)的变量都装箱为object之后再存储,读取的时候,还需要将这些数据进行拆箱操作。不仅影响了性能,而且还容易出现运行时错误。而泛型就是为了弥补这一点,在类,方法等的定义是使用占位符来声明数据的类型,比如说定义了一个List<int>的变量,则这个变量只能接受int类型的值,而不能接受string类型的值。这样既保证了性能(不用拆箱和装箱),而且还是类型安全(Type Safe)的。
   2. 泛型类型名称命名规则
       上面提到了站位符,理论上讲除了关键字之外都是可以用来当做站位符的。不过微软给出了一些建议:
      1.泛型类型名称应以T开头;
      2.如果该泛型类型没有任何约束,则可以简单的使用T来表示, 例如 Add<T>(T t1, T t2){ ... };
      3.如果该泛型存在约束,比如继承,或实现接口等,则尽量使用明确的名称,
                  比如 Add<TDocument>() where TDocument : IDocument
3. 泛型类
      泛型类是比较常见的,比如我们常用的List, Dictionary等都是泛型类。泛型类的定义是使用很方便,代码如下
      public class Document<T>
    {
      public Document()
      {}

      public Document(T title, T content)
      {
            this.Title = title;
            this.Content = content;
      }

      public T Title{get; set;}
      public T Content{get; set;}
    }
使用泛型类 Document<string> document = new Document<string>();就可以了。即在声明的时候将原来的占位符TDocument用需要使用的类型String替换就行了。
      1. 泛型类型的默认值(default value)。
          在使用反省类型的时候可能会用到占位符T的默认值。在这里不能直接将null赋值给T。因为null只能应用于引用类型(reference type), 而不能应用于值类型(value type)。为了能保证正确赋值,需要使用关键字default。即
          T temp= default(T);
          这样编译器就会根据实际情况自动赋值,比如给引用类型默认值为null,int类型默认值为0等。
      2. 约束(Constraints)
          使用约束的意义在于能够确保代码的正确性,减少不必要的运行时错误(runtime exception)。
         
内容说明
where T : struct T必须是值类型
where T : class T必须是引用类型
where T : IFoo T必须实现接口IFoo
where T : Foo T必须继承自Foo
where T : New() T必须包含默认构造函数
where T1 : T2 T1继承自另一个参数T2
   3. 继承
      当一个类(可以是泛型类,也可以是非泛型类)继承自一个泛型类的时候,有一定的要求:
      当子类是非泛型类的时候,父类(泛型类)没有约束;
       当子类是泛型类的时候,则要求父类和子类的占位符必须是相同的或是父类的占位符是明确的,
             例如 Child<T> : Base<T>或是 Child<T> : Base<string>
4. 泛型接口
      泛型接口和泛型类类似,在这里不做过多的描述
5. 泛型方法
      泛型方法的定义和泛型类是一样的,只不过对象有类变为方法。例如
   public void Swap<T>(T t1, T t2)
      { }
      在调用的时候, Swap<int>(int t1, int t2).因为编译器能够根据参数来自动推测出类型,所以也可以写成是
             Swap(int t1, int t2);泛型方法也有约束,和泛型类是一样的,可以参考上面的表格
6. 说明
      关于泛型委托会在写到委托的时候再说明。上面的内容更多的是知识性的文字,主要都是翻译自上面提到的那本书。如果有什么错误,欢迎大家指出来。并没有涉及到具体的代码。关于泛型类还有泛型方法的示例代码会在示例代码板块发布出来。应该会在明天(2013-03-13)发布到论坛里面

ibcadmin 发表于 2013-3-12 17:00:31

泛型是我一直准备要出的教程   你帮我出了 呵呵 谢谢啊 加精华了我下次出个List<T>

chao2332601 发表于 2013-6-16 03:34:49

谢谢分享!!!

Herit 发表于 2013-9-6 18:04:34

谢谢分享

C#爱好者 发表于 2013-9-12 16:50:24

多谢指教
页: [1]
查看完整版本: C#语言学习:泛型(Generics)