代码改变世界

【转】掌握C#自定义泛型类:从初始化说起

2012-02-10 11:35  cnb_mtime  阅读(561)  评论(0编辑  收藏  举报

继续【转】

Generic是Framework 2.0的新元素,中文名字称之为“泛型” ,特征是一个带有尖括号的类,比如List< T>

C#自定义泛型类用得最广泛,就是集合(Collection)中。实际上,泛型的产生其中一个原因就是为了解决原来集合类中元素的装箱和拆箱问题(如果对装箱和拆箱概念不明,请百度搜索)。由于泛型的使用,使得集合内所有元素都属于同一类,这就把类型不同的隐患消灭在编译阶段——如果类型不对,则编译错误。

这里只讨论C#自定义泛型类。基本自定义如下:

  1. public class MyGeneric < T>  
  2. ...{  
  3.     private T member;  
  4.     public void Method (T obj)  
  5.     ...{  
  6.     }  

这里,定义了一个泛型类,其中的T作为一个类,可以在定义的类中使用。当然,要定义多个泛型类,也没有问题。

  1. public class MyGeneric < TKey, TValue>  
  2. ...{  
  3.      private TKey key;  
  4.      private TValue value;  
  5.  
  6.      public void Method (TKey k, TValue v)  
  7.      ...{  
  8.      }  
  9. }  

泛型的初始化:泛型是需要进行初始化的。使用T doc = default(T)以后,系统会自动为泛型进行初始化。

限制:如果我们知道,这个将要传入的泛型类T,必定具有某些的属性,那么我们就可以在MyGeneric< T>中使用T的这些属性。这一点,是通过interface来实现的。

  1. // 先定义一个interface  
  2. public interface IDocument  
  3. ...{  
  4.    string Title ...{get;}  
  5.    string Content ...{get;}  
  6. }  
  7.  
  8. // 让范型类T实现这个interface  
  9. public class MyGeneric < T>  
  10. where T : IDocument  
  11. ...{  
  12.      public void Method(T v)  
  13.      ...{  
  14.           Console.WriteLine(v.Title);  
  15.      }  
  16. }  
  17.  
  18. // 传入的类也必须实现interface  
  19. public class Document : IDocument  
  20. ...{  
  21. ......  
  22. }  
  23.  
  24. // 使用这个泛型  
  25. MyGeneric< Document> doc = new MyGeneric< Document>(); 

泛型方法:我们同样可以定义泛型的方法

  1. void Swap< T> (ref T x, ref T y)  
  2. ...{  
  3. T temp = x;  
  4. x = y;  
  5. y = temp;  
  6. }  

泛型代理(Generic Delegate):既然能够定义泛型方法,自然也可以定义泛型代理

  1. public delegate void delegateSample < T> (ref T x, ref T y)  
  2.  
  3. private void Swap (ref T x, ref T y)  
  4. ...{  
  5.     T temp = x;  
  6.     x = y;  
  7.     y = temp;  
  8. }  
  9.  
  10. // 调用  
  11. public void Run()  
  12. ...{  
  13.    int i,j;  
  14.    i = 3;  
  15.    j = 5;  
  16.    delegateSample< int> sample = new delegateSample< int> (Swap);  
  17.    sample(i, j);  

设置可空值类型:一般来说,值类型的变量是非空的。但是,Nullable< T>可以解决这个问题。

  1. Nullable< int> x;   // 这样就设置了一个可空的整数变量x  
  2. x = 4;  
  3. x += 3;  
  4. if (x.HasValue)   // 使用HasValue属性来检查x是否为空  
  5. ...{ Console.WriteLine ("x="+x.ToString());  
  6. }  
  7. x = null;    // 可设空值 

使用ArraySegment< T>来获得数组的一部分。如果要使用一个数组的部分元素,直接使用ArraySegment来圈定不失为一个不错的办法。

  1. int[] arr = ...{1, 2, 3, 4, 5, 6, 7, 8, 9};  
  2. // 第一个参数是传递数组,第二个参数是起始段在数组内的偏移,第三个参数是要取连续多少个数  
  3. ArraySegment< int> segment = new ArraySegment< int>(arr, 2, 3);  // (array, offset, count)   
  4.  
  5. for (int i = segment.Offset; i< = segment.Offset + segment.Count; i++)  
  6. ...{  
  7.    Console.WriteLine(segment.Array[i]);    // 使用Array属性来访问传递的数组  

在例子中,通过将Offset属性和Count属性设置为不同的值,可以达到访问不同段的目的。

以上就是C#自定义泛型类的用法介绍。