0

0

C# 2.0 Specification(一)简介

黄舟

黄舟

发布时间:2017-01-03 10:10:01

|

1332人浏览过

|

来源于php中文网

原创

19.C#2.0介绍

c#2.0引入了几项语言扩展,其中最重要的是泛型、匿名方法、迭代器和不完整类型(partial type)。

泛型可以让类、结构、接口、委托和方法,通过他们所存储和操纵的数据的类型被参数化。泛型是很有用的,因为他们提供了更强的编译时类型检查,减少了数据类型之间的显式转换,以及装箱操作和运行时类型检查。 
匿名方法可以让代码块以内联的方式潜入到期望委托值的地方。匿名方法与lisp 编程语言中的λ函数(lambda function)相似。c#2.0支持“closures”的创建,在其中匿名方法可以访问相关局部变量和参数。 
迭代器是可以递增计算和产生值的方法。迭代器让类型指定foreach语句如何迭代它的所有元素,变得很容易。 
不完整类型可以让类、结构和接口被拆分成多个部分存储在不同的源文件中,这更利于开发和维护。此外,不完整类型允许某些类型的机器生成的部分与用户编写的部分之间的分离,因此增加由工具产生的代码很容易。


本章将介绍这些新特征。介绍完之后,接下来的四章提供了这些特征的完整的技术规范。

c#2.0的语言扩展主要被设计用于确保与现存的代码之间最大的兼容性。例如,尽管c#2.0对于where、yield 和partial这些词在特定上下文中赋予了特别的意义,但这些词仍然可被用作标识符。实际上,c# 2.0没有增加任何可能与现有代码中的标识符冲突的关键字。

19.1 泛型

泛型可以让类、结构、接口、委托和方法,通过他们所存储和操纵的数据的类型被参数化。C#泛型对于使用Eiffel或Ada的泛型的用户,或者对于C++模板的用户来说是很熟悉的;但他们将不用再去忍受后者的众多的复杂性。


19.1.1为什么使用泛型

没有泛型的话,通用目的的数据结构可以采用object类型存储任何类型的数据。例如,下面的Stack类在一个object数组中存储数据,而它的两个方法,Push和Pop相应地使用object接收和返回数据。

public class Stack
{
object[] items;
int count;
public void Push(object item){…}
public object Pop(){…}
}

尽管使用类型object可以使得Stack类更加灵活,但这样做也并不是没有缺点。例如,你可以将一个任何类型的值,诸如,Customer的一个实例压入(Push)堆栈。但当你取回一个值时,Pop方法的结果必须被显式地强制转换到合适的类型,为一个运行时类型检查去编写代码,以及带来的性能不利影响,是很令人讨厌的。

Stack stack = new Stack();
Stack.Push(new Customer());
Customer c = (Customer)stack.Pop();

如果一个值类型的值,例如一个int被传递到Push方法,它将会被自动装箱。当后面获得这个int 时,它必须使用一个显式的强制转换而被取消装箱。

Stack stack = new Stack(); 
Stack.Push(3);
int I = (int)stack.Pop();

这种装箱和取消装操作增加了性能开销,因为它们涉及到动态内存的分配和运行时类型检查。

Stack类的更大的问题是,它不能强制放置在堆栈上的数据种类。实际上,Customer实例可以被压入堆栈,而取回它时可能被强制转换到错误的类型。

Stack stack = new Stack();
Stack.Push(new Customer());
String s = (string)stack.Pop();

尽管先前的代码是Stack类的一种不恰当用法,但这段代码从技术上说是正确的,并且也不会报告编译时错误。问题直到代码执行时才会冒出来,在这一点上将会抛出一个InvalidCastException异常。

如果Stack类具有能够指定其元素的类型能力,那么很显然它能从这种能力得到好处。使用泛型,这将会变成可能。

19.1.2 创建和使用泛型

泛型为创建具有类型参数(type parameter)的类型提供了工具。下面的例子声明了一个带有类型参数T的泛型Stack类。类型参数在类名字之后的“”分界符中指定。这里没有object与别的类型之间的相互转换,Stack的实例接受它们被创建时的类型,并且存储那个类型的数据而没有转换它。类型参数T充当一个占位符,直到使用的时候才指定一个实际的类型。注意,T被用作内部items数组的元素类型、Push方法参数的类型和Pop方法的返回值类型。

Public class Stack
{
T[] items;
int count;
public void Push(T item){…}
public T Pop(){…}
}

当泛型类Stack被使用时,T所代替的实际类型将被指定。在下面的例子中,int 将被作为T的类型参数而给出。

95Shop仿醉品商城
95Shop仿醉品商城

95Shop可以免费下载使用,是一款仿醉品商城网店系统,内置SEO优化,具有模块丰富、管理简洁直观,操作易用等特点,系统功能完整,运行速度较快,采用ASP.NET(C#)技术开发,配合SQL Serve2000数据库存储数据,运行环境为微软ASP.NET 2.0。95Shop官方网站定期开发新功能和维护升级。可以放心使用! 安装运行方法 1、下载软件压缩包; 2、将下载的软件压缩包解压缩,得到we

下载
Stack stack = new Stack();
Stack.Push(3);
int x = stack.Pop();

Stack类型被称为构造类型(constructed type)。在Stack类型中,T的每次出现都被使用类型参数int代替。当Stack的实例被创建时,items数组的本地存储就是一个int[]而不是object[],与非泛型Stack相比,它提供了更高的存储效率。同样地,在int值上的Stack操作的Push和Pop方法,将会使得压入其他类型的值到堆栈中出现一个编译时错误,并且当取回值的时候也不需要转换回它们原始的类型。

泛型提供了强类型,意义例如压入一个int到Customer对象堆栈将会出现错误。就好像Stack被限制只能在int值上操作,同样Stack也被限制用于Customer对象。

对于下面的例子,编译器将会在最后两行报告错误。

Stack stack = new Stack();
Stack.Push(new Customer());
Customer c = stack.Pop();
stack.Push(3); //类型不匹配错误
int x = stack.Pop(); //类型不匹配错误

泛型类型声明可以有任意数量的类型参数。先前的Stack例子 只有一个类型参数,但一个通用的Dictionary类可能有两个类型参数,一个用于键(key)的类型,另一个用于值(value)的类型。

public class Dictionary
{
public void Add(K key , V value){…}
public V this[K key]{…}
}
当Dictionary 被使用时,必须提供两个类型参数。
Dictionary dict = new Dictionary();
Dict.Add(“Peter”, new Customer());
Custeomer c = dict[“Perter”];

19.1.3泛型类型实例化

与非泛型类型相似,被编译过的泛型类型也是由中间语言[Intermediate Language(IL)]指令和元数据表示。泛型类型的表示当然也对类型参数的存在和使用进行了编码。

当应用程序首次创建一个构造泛型类型的实例时,例如,Stack,.NET公共语言运行时的实时编译器(JIT)将在进程中把泛型IL和元数据转换为本地代码,并且将类型参数替换为实际的类型。对于那个构造泛型类型的后续引用将会使用相同的本机代码。从一个泛型类型创建一个特定构造类型的过程,称为泛型类型实例化(generic type instantiation)。[/b]

.NET公共语言运行时使用值类型为每个泛型类型实例创建了一个本地代码的特定拷贝,但对于所有的引用类型它将共享那份本地代码的单一拷贝(因为,在本地代码级别,引用只是带有相同表示的指针)。

19.1.4约束

一般来讲,泛型类不限于只是根据类型参数存储值。泛型类经常可能在给定类型参数的类型的对象上调用方法。例如,Dictionary类中的Add方法可能需要使用CompareTo方法比较键值。

public class Dictionary
{
public void Add(K key , V value)
{
…
if(key.CompareTo(x)<0){…}//错误,没有CompareTo方法
…
}
}

因为为K所指定的类型参数可能是任何类型,可以假定key参数存在的唯一成员,就是那些被声明为object类型的,例如,Equals,GetHashCode和ToString;因此,在先前例子中将会出现编译时错误。当然,你可以将key参数强制转换到一个包含CompareTo方法的类型。例如,key参数可能被强制转换到IComparable接口。

public class Dictionary
{
public void Add(K key , V value)
{
…
if(((IComparable)key).CompareTo(x)<0){…}
…
}
}

尽管这种解决办法有效,但它需要在运行时的动态类型检查,这也增加了开销。更糟糕的是,它将错误报告推迟到了运行时,如果键(key)没有实现IComparable接口将会抛出InvalidCastException异常。

为了提供更强的编译时类型检查,并减少类型强制转换,C#允许为每个类型参数提供一个约束(constraint)的可选的列表。类型参数约束指定了类型必须履行的一种需求,其目的是为了为类型参数被用作实参(argument)。约束使用单词where声明,随后是类型参数的名字,接着是类或接口类型的列表,和可选的构造函数约束new()。

public class Dictionary where K :IComparable
{
public void Add(K key , V value)
{
…
if(key.CompareTo(x)<0){…}
…
}
}

给定这个声明,编译器将会确保K的任何类型实参是实现了IComparable接口的类型。

并且,在调用CompareTo方法之前也不再需要对key参数进行显式地强制转换。为类型参数作为一个约束而给出的类型的所有成员,对于类型参数类型的值时直接有效的。

对于一个给定的类型参数,你可以指定任意数量的接口作为约束,但只能有一个类。每个约束的类型参数有一个单独的where 语句。在下面的例子中,类型参数K有两个接口约束,类型参数e有一个类约束和一个构造函数约束。

public class EntityTable
where K:IComparable,IPersisable
where E:Entity, new()
{
public void Add(K key , E entity)
{
…
if(key.CompareTo(x)<0){…}
…
}
}

在前面的例子中,构造函数约束new(),确保为E用作类型参数的类型具有一个公有的、无参数构造函数,并且它允许泛型类使用new E()创建该类型的实例。

类型参数约束应该很小心的使用。尽管它们提供了更强的编译时类型检查,在某些情况下增强了性能,但它们也限制了泛型类型的可能的用法。例如,泛型类List可能约束T实现IComparable接口,由此它的Sort方法将可以比较项的大小。然而,这么做却使得没有实现IComparable 接口的类型不能使用List,即使是在这些情形下,Sort方法根本就没有被调用过。

以上就是C# 2.0 Specification(一)简介的内容,更多相关内容请关注PHP中文网(www.php.cn)!


热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

14

2026.01.30

c++ 字符串格式化
c++ 字符串格式化

本专题整合了c++字符串格式化用法、输出技巧、实践等等内容,阅读专题下面的文章了解更多详细内容。

9

2026.01.30

java 字符串格式化
java 字符串格式化

本专题整合了java如何进行字符串格式化相关教程、使用解析、方法详解等等内容。阅读专题下面的文章了解更多详细教程。

12

2026.01.30

python 字符串格式化
python 字符串格式化

本专题整合了python字符串格式化教程、实践、方法、进阶等等相关内容,阅读专题下面的文章了解更多详细操作。

4

2026.01.30

java入门学习合集
java入门学习合集

本专题整合了java入门学习指南、初学者项目实战、入门到精通等等内容,阅读专题下面的文章了解更多详细学习方法。

20

2026.01.29

java配置环境变量教程合集
java配置环境变量教程合集

本专题整合了java配置环境变量设置、步骤、安装jdk、避免冲突等等相关内容,阅读专题下面的文章了解更多详细操作。

18

2026.01.29

java成品学习网站推荐大全
java成品学习网站推荐大全

本专题整合了java成品网站、在线成品网站源码、源码入口等等相关内容,阅读专题下面的文章了解更多详细推荐内容。

19

2026.01.29

Java字符串处理使用教程合集
Java字符串处理使用教程合集

本专题整合了Java字符串截取、处理、使用、实战等等教程内容,阅读专题下面的文章了解详细操作教程。

3

2026.01.29

Java空对象相关教程合集
Java空对象相关教程合集

本专题整合了Java空对象相关教程,阅读专题下面的文章了解更多详细内容。

6

2026.01.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 8万人学习

C 教程
C 教程

共75课时 | 4.3万人学习

C++教程
C++教程

共115课时 | 14.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号