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

原创 2004年07月20日 21:41:00

其他范型类

.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 抽象类实现了 IListICollection 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; // b10

 

以后,在设计可能返回无效值的 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);

...

不可不懂的.NET基础知识

刚开始接触.NET很疑惑,看完视频也不是太懂,通过总结和反复,从概括和概念入手,慢慢变得清晰了。这篇博客主要是我对.NET基础知识的了解,算作积累吧。 .NET框架体系结构 由四个主要部分...
  • zhuanzhe117
  • zhuanzhe117
  • 2013年05月21日 13:39
  • 5311

.NET 2.0 使用最新版的JSON.net 进行反序列化

大家知道 JSON.net 最新版是基于.net 3.5 框架的,要如何使其工作在 .NET 2.0框架下呢,当然是GOOGLE + baidu 啦,幸不辱命,终于在一篇英文的博客中找到了解决方法,地...
  • lvjin110
  • lvjin110
  • 2013年12月09日 19:35
  • 3168

NET 2.0 基础类库中的范型

其他范型类  .NET 2.0 基础类库对范型的应用当然并不仅限于范型集合和 Functional Programming。下面所列的范型类也都有其明确的设计目的和用途。 Array  在.NE...
  • u014660355
  • u014660355
  • 2014年04月19日 18:07
  • 157

.Net Standard扩展支持实例分享

上篇(.Net基础体系和跨框架开发普及)介绍了.Net当前生态下的大概情况,也分享了简单实现的过程,这篇文章就是讲解我的OSS.Common项目扩展.Net Standard 支持的过程,主要集中在:...
  • swywkc2i
  • swywkc2i
  • 2017年02月15日 21:19
  • 1348

.net ef core 领域设计代码转换(上篇)

一、前言 .net core 2.0正式版已经发布几个月了,经过研究,决定把项目转移过来,新手的话可以先看一些官方介绍 传送门:https://docs.microsoft.com/zh-cn/d...
  • sD7O95O
  • sD7O95O
  • 2017年11月12日 00:00
  • 267

ADO.NET 2.0中的异步命令执行

http://www.cnblogs.com/haowenbiao/archive/2008/05/11/1192768.html 在ADO.NET 2.0版本中,我们不仅希望使现有的方案更为简...
  • mituan1234567
  • mituan1234567
  • 2014年03月05日 15:41
  • 574

C# .NET4.0 改为 到.NET2.0 报错解决方法

如今的VS开发工具都是VS2012或者VS2015版本,高版本开发的程序默认使用的都是.NET4.0或者更高的框架,其他电脑在运行该程序时需要安装对应版本的.NET。目前winXP和Win7系统默认都...
  • yinjun151
  • yinjun151
  • 2016年05月24日 17:30
  • 1930

如何手动删除并重新安装 .NET Framework 2.0

如何手动删除并重新安装 .NET Framework 2.0 本文可能包含一个指向 Windows 安装程序清理实用程序 ...
  • luoye7422
  • luoye7422
  • 2015年04月01日 23:37
  • 4303

来腾讯云开发者实验室 学习.NET Core 2.0

腾讯云开发者实验室为开发者提供了一个零门槛的在线实验平台,开发者实验室提供的能力:零门槛扫码即可免费领取实验机器,支持使用自有机器参与,实验完成后支持保留实验成果;在线 WEB IDE 支持 shel...
  • sD7O95O
  • sD7O95O
  • 2017年12月24日 00:00
  • 442

轻松把玩HttpClient之封装HttpClient工具类(一)(现有网上分享中的最强大的工具类)

搜了一下网络上别人封装的HttpClient,大部分特别简单,有一些看起来比较高级,但是用起来都不怎么好用。调用关系不清楚,结构有点混乱。所以也就萌生了自己封装HttpClient工具类的想法。要做就...
  • xiaoxian8023
  • xiaoxian8023
  • 2015年11月19日 11:20
  • 26705
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:.NET 2.0 基础类库中的范型——其他范型类
举报原因:
原因补充:

(最多只允许输入30个字)