现在的位置: 首页 > 综合 > 正文

泛型(C# 2。0 编程指南)

2012年12月12日 ⁄ 综合 ⁄ 共 4464字 ⁄ 字号 评论关闭

C#泛型秘诀(1)

本系列文章翻译O'Reilly 出版的《C# Cookbook》一书中的片段,仅供学习交流使用
 

4.0 介绍

泛型,一个期待已久的功能,随着C# 2.0版本编译器的到来最终出现。泛型是一个非常有用的功能,它使得您的代码变得精简而富有效率。这些将在秘诀4.1进行详细讲述。泛型的到来使得您可以编写更为强大的应用程序,但这需要正确地使用它。如果您考虑把ArrayListQueueStackHashtable对象转变为使用相应的泛型版本,可以阅读秘诀4.44.54.10。当您阅读过后,会发现这种转变不一定简单,甚至有可能会不再打算进行转变。

       本章的另外一些秘诀涉及到.NET Framework 2.0所包含的其他泛型类,如秘诀4.6。其他秘诀讲述一些泛型类的操作,如秘诀4.24.84.13

 

4.1决定在何时何地使用泛型

问题

您希望在一个新工程内使用泛型,或者想把已有项目中的非泛型类转换为等价的泛型版本。但您并非了解为何要这样做,也不知道哪个非泛型类应该被转换为泛型类。

解决方案

决定在何时何地使用泛型,您需要考虑以下几件事件:

l         您所使用的类型是否包含或操作未指定的数据类型(如集合类型)?如果是这样,如果是这样,创建泛型类型将能提供更多的好处。如果您的类型只操作单一的指定类型,那么就没有必要去创建一个泛型类。

l         如果您的类型将操作值类型,那么就会产生装箱和拆箱操作,就应该考虑使用泛型来防止装箱和拆箱操作。

l         泛型的强类型检查有助于快速查找错误(也就是编译期而非运行期),从而缩短bug修复周期。

l         在编写多个类操作多个数据类型时是否遭遇到“代码膨胀”问题(如一个ArrayList只存储StreamReaders而另一个存储StreamWriters)?其实编写一次代码并让它工作于多个数据类型非常简单。

l         泛型使得代码更为清晰。通过消除代码膨胀并进行强制检查,您的代码将变得更易于阅读和理解。

讨论

很多时候,使用泛型类型将使您受益。泛型将使得代码重用更有效率,具有更快的执行速度,进行强制类型检查,获得更易读的代码。

阅读参考

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),它的长度由构造方法中的传递的参数来决定。它实现了添加和获得项的方法(AddItemGetItem),还有一个只读属性来获取数组中的项的数目(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>通过使用类型参数指示允许使用的对象类型来提供类型安全。

下一个不同在于AddItemGetItem方法的声明。AddItem现在使用一个类型T做为参数,而在StandardClass中使用object类型做为参数。GetItem现在的返回值类型TStandardClass返回值为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)

抱歉!评论已关闭.