当前位置:首页 > 技能相关 > C#与C++ > 正文内容

c#高级编程 泛型(五)

admin2年前 (2023-01-30)C#与C++2580 修订时间:2023-02-01 08:53:08

1、泛型概述

泛型是C#和.NET的一个重要概念。泛型不仅是C#编程语言的一部分,而且与程序集中的IL(Intermediate Language,中间语言)代码紧密地集成。有了泛型,就可以创建独立于被包含类型的类和方法。我们不必给不同的类型编写功能相同的许多方法或类,只创建一个方法或类即可。

另一个减少代码的选项是使用Object类,但使用派生自Object类的类型进行传递不是类型安全的。泛型类使用泛型类型,并可以根据需要用特定的类型替换泛型类型。这就保证了类型安全性:如果某个类型不支持泛型类,编译器就会出现错误。

下面介绍泛型的优点和缺点,尤其是:

● 性能

● 类型安全性

● 二进制代码重用

● 代码的扩展

● 命名约定

1.1 性能

泛型的一个主要优点是性能。对值类型使用非泛型集合类,在把值类型转换为引用类型,和把引用类型转换为值类型时,需要进行装箱和拆箱操作。

值类型存储在栈上,引用类型存储在堆上。C#类是引用类型,结构是值类型。例如,int可以赋予一个对象。从值类型转换为引用类型称为装箱。如果方法需要把一个对象作为参数,同时传递一个值类型,装箱操作就会自动进行。另一方面,装箱的值类型可以使用拆箱操作转换为值类型。在拆箱时,需要使用类型强制转换运算符。

下面的例子显示了System.Collections名称空间中的ArrayList类。ArrayList存储对象,Add()方法定义为需要把一个对象作为参数,所以要装箱一个整数类型。在读取ArrayList中的值时,要进行拆箱,把对象转换为整数类型。可以使用类型强制转换运算符把ArrayList集合的第一个元素赋予变量i1,在访问int类型的变量i2的foreach语句中,也要使用类型强制转换运算符:

var list = new ArrayList();
list.Add(44); 
int i1 = (int)list[0]; 
foreach (int i2 in list)
{
WriteLine(i2); 
}

装箱和拆箱操作很容易使用,但性能损失比较大,遍历许多项时尤其如此。

System.Collections.Generic名称空间中的List<T>类不使用对象,而是在使用时定义类型。在下面的例子中,List<T>类的泛型类型定义为int,所以int类型在JIT(Just-In-Time)编译器动态生成的类中使用,不再进行装箱和拆箱操作:

var list = new List<int>();
list.Add(44); 
int i1 = list[0]; 
foreach (int i2 in list)
{
WriteLine(i2);
}

1.2 类型安全

泛型的另一个特性是类型安全。与ArrayList类一样,如果使用对象,就可以在这个集合中添加任意类型。下面的例子在ArrayList类型的集合中添加一个整数、一个字符串和一个MyClass类型的对象:

var list = new ArrayList();
list.Add(44);
list.Add("mystring");
list.Add(new MyClass());

如果这个集合使用下面的foreach语句迭代,而该foreach语句使用整数元素来迭代,编译器就会接受这段代码。但并不是集合中的所有元素都可以强制转换为int,所以会出现一个运行时异常:

foreach (int i in list)
{
WriteLine(i);
}

在泛型类List<T>中,泛型类型T定义了允许使用的类型。有了List<int>的定义,就只能把整数类型添加到集合中。编译器不会编译这段代码,因为Add()方法的参数无效:

var list = new List<int>();
list.Add(44);
list.Add("mystring"); // 编译时错误
list.Add(new MyClass()); // 编译时错误

1.3 二进制代码的重用

泛型允许更好地重用二进制代码。泛型类可以定义一次,并且可以用许多不同的类型实例化。

例如,System.Collections.Generic名称空间中的List<T>类用一个int、一个字符串和一个MyClass类型实例化:

var list = new List<int>();
list.Add(44);

var stringList = new List<string>();
stringList.Add("mystring");

var myClassList = new List<MyClass>();
myClassList.Add(new MyClass());

1.4 命名约定

如果在程序中使用泛型,在区分泛型类型和非泛型类型时就会有一定的帮助。下面是泛型类型的命名规则:

(1)泛型类型的名称用字母T作为前缀。

(2)如果没有特殊的要求,泛型类型允许用任意类替代,且只使用了一个泛型类型,就可以用字符T作为泛型类型的名称。

public class List<T> { }
public class LinkedList<T> { }

 (3)如果泛型类型有特定的要求(例如,它必须实现一个接口或派生自基类),或者使用了两个或多个泛型类型,就应给泛型类型使用描述性的名称:

public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);
public delegate TOutput Converter<TInput, TOutput>(TInput from);
public class SortedList<TKey, TValue> { }
































 您阅读本篇文章共花了: 

免责声明
本站内容均为博客主本人日常使用记录的存档,如侵犯你的权益请联系:lifei@zaiheze.com 546262132@qq.com 沟通删除事宜。本站仅带访问端口形式使用,已杜绝搜索引擎爬取。

扫描二维码推送至手机访问。

版权声明:本文由LIFEI - blog发布,如需转载请注明出处。

本文链接:http://www.lifeiai.com/?id=290

分享给朋友:

相关文章

Web API的创建3年前 (2022-11-07)
C# 第一篇 踏上征程 3年前 (2022-11-14)
C# 第四篇 数组定义3年前 (2022-11-15)
C# 第五篇 字符串3年前 (2022-11-15)

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。