.NET 2.0 基础类库中的范型――其他范型类

.NET  2.0  基础类库中的范型――其他范型类
时间:
2007 - 05 - 01  阅读: 13  类型:转载 编辑:jjxz   
其他范型类
.NET 
2.0  基础类库对范型的应用当然并不仅限于范型集合和 Functional Programming。下面所列的范型类也都有其明确的设计目的和用途。

Array
在.NET 
2 .0中,Array 类扩充了对范型编程的支持。当然,Array类本身并不是范型类(出于兼容的考虑),而是提供了一系列支持范型的方法。除了前面提到的 Functional Programming 的支持外,Array 类还对以前很多基于  object  的方法提供了对应的范型版本,这样对值类型可以提高查找和排序时的性能。例如:



static   int  IndexOf(T[] array, T value);

static   void  Sort(T[] array);



另外,还添加了一些新的范型方法,例如:



static  IList AsReadOnly(T[] array);  //  返回一个只读的列表

static   void  Resize( ref  T[] array,  int  newSize);  //  改变数组大小



还有一个好消息是,在 .NET 
2.0  中,数组将支持范型集合接口。我们知道,在 .NET  2.0  以前,Array 抽象类实现了 IList,ICollection 和 IEnumerable 集合接口,这样我们可以在需要传入这些接口的地方传入数组。在 .NET  2.0  中,范型集合需要使用如 IEnumerable < T >  这样的范型接口,所以数组也将支持这些范型接口。然而,这些范型接口并不在 Array 类中实现(因为 Array 类本身并不是范型类),而是在运行时由 CLR 实现。例如,对于  int [],可以按如下的伪定义理解它的实现:



class   int [] : Array, List < int > , ICollection < int > , IEnumerable < int >

ArraySegment
< T >
ArraySegment
< T >  表示数组中的一段。我们知道,C# / CLR 没有提供默认参数这一特性,而是要求使用函数重载。所以,不少类中有大量的针对数组参数(索引,长度)的重载方法(为了方便调用者),例如:



class  Encoding  {

public virtual byte[] GetBytes(char[] chars);

public virtual byte[] GetBytes(char[] chars, int index, int count);

...

}




对类的设计者来说,提供如此多的重载显得麻烦和笨拙,而且这些重载方法实际上都对应同一个实现。另外,设计如此多的虚函数也给子类的实现者带来了不少麻烦,尤其是当这些函数是 
abstract  时。

在 .NET 
2.0  中,微软试图通过提供 ArraySegment < T >  类来解决这一设计问题。使用 ArraySegment < T >  的话,类的设计者现在只需设计一个方法即可,即:(注意这不是 .NET  2.0  的真实代码,仅为说明问题)



class  Encoding  {

public virtual byte[] GetBytes(ArraySegment<char> chars);

...

}




而由调用者来决定如何传入数组参数,例如:



char [] chars  =  ...;

byte [] bytes  =  enc.GetBytes( new  ArraySegment < char > (chars));



byte [] bytes  =  enc.GetBytes( new  ArraySegment < char > (chars,  0 10 ));



可以看到,使用 ArraySegment
< char >  的缺点是对使用者来说要多编写一些代码。可能是这个原因,所以目前 .NET 中并没有正式开始使用它。另外一个原因则可能是出于要和已有设计保持一致的考虑。

Nullable
< T >
Nullable
< T >  值类型用于表示可能无效或者不存在的值(这个类最初的命名为 OptionalValue < T > )。例如,在数据库设计中可能有些字段是可选,数据访问接口的设计者可以用 Nullable < T >  来返回数据库字段。Nullable < T >  类有两个只读实例属性 HasValue 和 Value。前者是  bool  类型用于标识是否有效,后者是 T 类型的数据。在访问 Value 之前必须先判断 HasValue 是否为  true ,否则将抛出异常。

Nullable
< T >  通常用于值类型(如 Nullable < DateTime > ),因为对引用类型来说, null  本身就可以代表无效的状态,在这种情况下使用 Nullable < T >  并没有太多意义。

值得一提的是,C# 
2.0  为 Nullable < T >  类型提供了一个非常简洁而优美的语法,即在原始类型后加  ?  后缀,也就是说, int ?  等于 Nullable < int > 。这样使得 Nullable < T >  在 C# 中的使用非常的容易和自然(毕竟模板看起来要费眼一些J)。例如下面的代码示例:



int ?  a  =   null //  a为空(即HasValue属性为false)

int ?  b  =   10 //  b为10



以后,在设计可能返回无效值的 API 时,除了以前使用的抛出异常的方法外,我们也可以使用 Nullable
< T > ,例如:



int  ParseNumber( string  s);  //  使用异常

int ?  TryParseNumber( string  s);  //  不使用异常,而使用Nullable<T>

EventHandler
< T >
事件的定义和使用遍及 .NET Framework 的各个角落。在没有范型的情况下,每个事件委托都要单独定义,例如:



delegate   void  EventHandler( object  sender, EventArgs e);

delegate   void  KeyEventHandler( object  sender, KeyEventArgs e);



这样的缺点是对事件定义者来说每次都要定义新的事件委托,而对使用者来说又要多学习和记忆新的事件委托。在 .NET 
2.0  中,引入了 EventHandler 范型事件委托来解决这个问题,它的原型如下(注意它位于 System.Collections.Generic 命名空间中):



delegate   void  EventHandler( object  sender, T e)  where  T: EventArgs;



使用 EventHandler 的话,就不需要自己定义新的事件委托了,仅需提供自己的事件参数类即可(需要从 EventArgs 派生)。这样的好处一方面是可用性更好(无论对事件定义者还是使用者),另外从 CLR 的角度来说,因为这个范型委托编译后对所有 T 类型都只对应一个二进制实现,所以会提高系统的整体性能。所以,在微软最新的设计指南中,建议事件委托使用 EventHandler
< T > 。使用 EventHandler < T >  的代码示例如下:



class  MyEventArgs : EventArgs  {

...

}




class  Foo  {

public event EventHandler<MyEventArgs> MyEvent;

...

}




Foo foo 
=   new  Foo();

foo.MyEvent 
+=   new  EventHandler < MyEventArgs > ( this .MyEventHandler);

...
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值