没有合适的资源?快使用搜索试试~ 我知道了~
首页C#泛型详细介绍与实例说明(详细)
资源详情
资源评论
资源推荐
决定在何时何地使用泛型
问题
您希望在一个新工程内使用泛型,或者想把已有项目中的非泛型类转换为等价的泛型版本。但您并非了解为何要这
样做,也不知道哪个非泛型类应该被转换为泛型类。
解决方案
决定在何时何地使用泛型,您需要考虑以下几件事件:
您所使用的类型是否包含或操作未指定的数据类型(如集合类型)?如果是这样,如果是这样,创建泛型类型将能
提供更多的好处。如果您的类型只操作单一的指定类型,那么就没有必要去创建一个泛型类。
如果您的类型将操作值类型,那么就会产生装箱和拆箱操作,就应该考虑使用泛型来防止装箱和拆箱操作。
泛型的强类型检查有助于快速查找错误(也就是编译期而非运行期),从而缩短 bug 修复周期。
在编写多个类操作多个数据类型时是否遭遇到“代码膨胀”问题(如一个 ArrayList 只存储 StreamReaders 而另一个存
储 StreamWriters)?其实编写一次代码并让它工作于多个数据类型非常简单。
泛型使得代码更为清晰。通过消除代码膨胀并进行强制检查,您的代码将变得更易于阅读和理解。
讨论
很多时候,使用泛型类型将使您受益。泛型将使得代码重用更有效率,具有更快的执行速度,进行强制类型检查,
获得更易读的代码。
阅读参考
MSDN 文档中的“Generics Overview”和“Benefits of Generics”主题。
4.2 理解泛型类型
问题
您需要理解泛型类型在.NET 中是如何工作的,它跟一般的.NET 类型有什么不同。
解决方案
几个小实验就可以演示一般类型和泛型类型之间的区别。例 4-1 中的 StandardClass 类就是一个般类型。
例
4-1 StandardClass
:一般的
.NET
类型
public class StandardClass
{
static int _count = 0; //StandardClass 类的对象的表态计数器
int _maxItemCount; //项数目的最大值
object[] _items; //保存项的数组
int _currentItem = 0; //当前项数目
public StandardClass(int items) //构造函数
{
_count++; //对象数目加
_maxItemCount = items;
_items = new object[_maxItemCount]; //数组初始化
}
//用于添加项,为了适用于任何类型,使用了 object 类型
public int AddItem(object item)
{
if (_currentItem < _maxItemCount)
{
_items[_currentItem] = item;
return _currentItem++; //返回添加的项的索引
}
else
throw new Exception("Item queue is full");
}
//用于从类中取得指定项
public object GetItem(int index)
{
Debug.Assert(index < _maxItemCount); //设置断言
if (index >= _maxItemCount)
throw new ArgumentOutOfRangeException("index");
return _items[index]; //返回指定项
}
public int ItemCount //属性,指示当前项数目
{
get { return _currentItem; }
}
public override string ToString( )
{ //重载 ToString 方法,用于介绍类的情况
return "There are " + _count.ToString( ) +
" instances of " + this.GetType( ).ToString( ) +
" which contains " + _currentItem + " items of type " +
_items.GetType( ).ToString( ) + " ";
}
}
StandardClass 类有一个整型静态成员变量_count,用于在实例构造器中计数。重载的 ToString()方法打印在这个
应用程序域中 StandardClass 类实例的数目。StandardClass 类还包括一个 object 数组(_item),它的长度由构造
方法中的传递的参数来决定。它实现了添加和获得项的方法(AddItem,GetItem),还有一个只读属性来获取数组
中的项的数目(ItemCount)。
GenericClass<T>类是一个泛型类型,同样有静态成员变量_count,实例构造器中对实例数目进行计算,重载的
ToString()方法告诉您有多少 GenericClass<T>类的实例存在。GenericClass<T>也有一个_itmes 数组和
StandardClass 类中的相应方法,请参考例 4-2。
Example4-2 GenericClass<T>
:泛型类
public class GenericClass<T>
{
static int _count = 0;
int _maxItemCount;
T[] _items;
int _currentItem = 0;
public GenericClass(int items)
{
_count++;
_ _maxItemCount = items;
_items = new T[_maxItemCount];
}
public int AddItem(T item)
{
if (_currentItem < _maxItemCount)
{
_items[_currentItem] = item;
return _currentItem++;
}
else
throw new Exception("Item queue is full");
}
public T GetItem(int index)
{
Debug.Assert(index < _maxItemCount);
if (index >= _maxItemCount)
throw new ArgumentOutOfRangeException("index");
return _items[index];
}
public int ItemCount
{
get { return _currentItem; }
}
public override string ToString()
{
return "There are " + _count.ToString() +
" instances of " + this.GetType().ToString() +
" which contains " + _currentItem + " items of type " +
_items.GetType().ToString() + " ";
}
}
从 GenericClass<T>中的少许不同点开始,看看_items 数组的声明。它声明为:
T[] _items;
而不是
object[] _items;
_items 数组使用泛型类(<T>)做为类型参数以决定在_itmes 数组中接收哪种类型的项。StandarClass 在_itmes 数
组中使用 Objcec 以使得所有类型都可以做为项存储在数组中(因为所有类型都继承自 object)。而 GenericClass<T>
通过使用类型参数指示允许使用的对象类型来提供类型安全。
下一个不同在于 AddItem 和 GetItem 方法的声明。AddItem 现在使用一个类型 T 做为参数,而在 StandardClass 中
使用 object 类型做为参数。GetItem 现在的返回值类型 T,StandardClass 返回值为 object 类型。这个改变允许
GenericClass<T>中的方法在数组中存储和获得具体的类型而非 StandardClass 中的允许存储所有的 object 类型。
public int AddItem(T item)
{
if (_currentItem < _maxItemCount)
{
_items[_currentItem] = item;
return _currentItem++;
}
else
throw new Exception("Item queue is full");
}
public T GetItem(int index)
{
Debug.Assert(index < _maxItemCount);
if (index >= _maxItemCount)
throw new ArgumentOutOfRangeException("index");
return _items[index];
}
这样做的优势在于,首先通过 GenericClass<T>为数组中的项提供了类型安全。在 StandardClass 中可能会这样写
代码:
// 一般类
StandardClass C = new StandardClass(5);
Console.WriteLine(C);
string s1 = "s1";
string s2 = "s2";
string s3 = "s3";
int i1 = 1;
// 在一般类中以 object 的形式添加项
C.AddItem(s1);
C.AddItem(s2);
C.AddItem(s3);
// 在字符串数组中添加一个整数,也被允许
C.AddItem(i1);
但在 GenericClass<T>中做同样的事情将导致编译错误:
// 泛型类
GenericClass<string> gC = new GenericClass<string>(5);
Console.WriteLine(gC);
string s1 = "s1";
string s2 = "s2";
string s3 = "s3";
int i1 = 1;
// 把字符串添加进泛型类.
gC.AddItem(s1);
gC.AddItem(s2);
gC.AddItem(s3);
// 尝试在字符串实例中添加整数,将被编译器拒绝
// error CS1503: Argument '1': cannot convert from 'int' to 'string'
//GC.AddItem(i1);
编译器防止它成为运行时源码的 bug,这是一件非常美妙的事情。
虽然并非显而易见,但在 StandardClass 中把整数添加进 object 数组会导致装箱操作,这一点可以 StandardClass
调用 GetItem 方法时的 IL 代码:
IL_0170: ldloc.2
IL_0171: ldloc.s i1
IL_0173: box [mscorlib]System.Int32
IL_0178: callvirt instance int32
CSharpRecipes.Generics/StandardClass::AddItem(object)
这个装箱操作把做为值类型的整数转换为引用类型(object),从而可以在数组中存储。这导致了在 object 数组中
存储值类型时需要增加额外的工作。
当您在运行 StandardClass 并从类中返回一个项时,还会产生一个问题,来看看 StandardClass.GetItem 如何返回
一个项:
// 存储返回的字符串.
string sHolder;
// 发生错误 CS0266:
// Cannot implicitly convert type 'object' to 'string'…
剩余61页未读,继续阅读
thomas3210
- 粉丝: 1
- 资源: 17
上传资源 快速赚钱
- 我的内容管理 收起
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
会员权益专享
最新资源
- c++校园超市商品信息管理系统课程设计说明书(含源代码) (2).pdf
- 建筑供配电系统相关课件.pptx
- 企业管理规章制度及管理模式.doc
- vb打开摄像头.doc
- 云计算-可信计算中认证协议改进方案.pdf
- [详细完整版]单片机编程4.ppt
- c语言常用算法.pdf
- c++经典程序代码大全.pdf
- 单片机数字时钟资料.doc
- 11项目管理前沿1.0.pptx
- 基于ssm的“魅力”繁峙宣传网站的设计与实现论文.doc
- 智慧交通综合解决方案.pptx
- 建筑防潮设计-PowerPointPresentati.pptx
- SPC统计过程控制程序.pptx
- SPC统计方法基础知识.pptx
- MW全能培训汽轮机调节保安系统PPT教学课件.pptx
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论2