小新的技术天地

Make It Works !

博客园 首页 新随笔 联系 订阅 管理

作者:Ahmed Abd ElGhany  译者:小新0574

Generics are the most useful C# 2.0 language extensions, beside Anonymous methods, Iterators, Partial types And Nullable types.

 

比较匿名方法,迭代器,不完全类型,可空类型而言,泛型是C#2.0中最有用的扩展。

What are generics?
Generics permit classes, structs, interfaces, delegates, and methods to be parameterized by the types of data they store and manipulate.

 

什么是泛型?

泛型允许类,结构,接口,委托和方法来根据它们所保存和维护的数据的类型而参数化。

Why generics?
To well know the useful of generics lets examine the following code:--

为什么需要泛型呢?

为了大家知道泛型的有用的地方,让我们来考察一下下面的代码:--

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


 

We use the object type to store any type of data. The above simple Stack class stores its data in an object array, and its two methods, Push and Pop, use object to accept and return data. While the use of type object makes the Stack class very flexible, it is not without drawbacks. For example, it is possible to push a value of any type, such a Customer instance, onto a stack.

 

我们使用object类型,这样可以存储任何类型数据。上面简单的堆栈类把它的数据储存在一个object数组里,它的两个方法,PushPop,使用object类型来接受和返回数据。使用object类型使得堆栈类非常灵活,不过这样做也不是没有缺点。举例来说,任何类型的值比如说,一个Customer类型的实例,都可能被压进堆栈。

However, when a value is retrieved, the result of the Pop method must explicitly be cast back to the appropriate type, which is tedious to write and carries a performance penalty for run-time type checking:

 

然而,当一个值被返回后,Pop方法返回的值必须显式地转化为适当的类型,这样使得写起来很单调乏味,同时使得运行时的类型检查损伤性能:

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

 

If a value of a value type, such as an int, is passed to the Push method, it is automatically boxed. When the int is later retrieved, it must be unboxed with an explicit type cast:

如果一个值类型的值,比如说int,被传递给Push方法,它就被自动装箱了。当一个int稍后被返回后,他必须用显式的类型转换拆箱:
Stack stack = new Stack();
stack.Push(
3);
int i = (int)stack.Pop();

 

Such boxing and unboxing operations add performance overhead since they involve dynamic memory allocations and run-time type checks.

这种装箱拆箱的操作,包括在动态内存分配和运行时检查里,增加了性能负担。

A further issue with the Stack class is that it is not possible to enforce the kind of data placed on a stack. Indeed, a Customer instance can be pushed on a stack and then accidentally cast it to the wrong type after it is retrieved:

对于堆栈类更深远的一个问题是,它不可能强迫某种类型数据放在堆栈上。确实,一个Customer实例可以被压入堆栈,然后在它被返回时,意外地转化为错误的类型。

 

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

 

While the code above is an improper use of the Stack class, the code is technically speaking correct and a compile-time error is not reported. The problem does not become apparent until the code is executed, at which point an InvalidCastException is thrown.

上面的代码是堆栈类一种不恰当的使用方法,而这段代码却技术性的被认识正确的,没有报告编译时错误。这个问题直到代码被执行时才显现出来,这时抛出了一个InvalidCastException异常。

With generics those problems are all solved. HOW ??

使用泛型这些问题就可以都被解决了,怎么做??

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

 

When the generic class Stack<T> is used, the actual type to substitute for T is specified. In the following example, int is given as the type argument for T:

当使用泛型类使用Stack<T>时,实际的类型代替T。在下面的例子中,int被使用为T的类型参数:


Stack<int> stack = new Stack<int>();
stack.Push(
3);
int x = stack.Pop();


 

The Stack<int> type is called a constructed type. In the Stack<int> type, every occurrence of T is replaced with the type argument int. When an instance of Stack<int> is created, the native storage of the items array is an int[] rather than object[], providing substantial storage efficiency compared to the non-generic Stack. Likewise, the Push and Pop methods of a Stack<int> operate on int values, making it a compile-time error to push values of other types onto the stack, and eliminating the need to explicitly cast values back to their original type when they’re retrieved.

Stack<int>类型被称为构造类型。在Stack<int>类型中,每一处出现T的地方都被类型参数int代替了。当Stack<int>的一个实例被创建,本地储存的items数组是一个int[]而不是object[],比较不使用泛型的Stack类,提供了储存真实类型的数据的效率。同样地,Stack<int>PushPop方法操作int值,使得在压入其他类型的值进栈时,出现一个编译时错误。不需要在它们被返回时,显式地把它们的值转化为它们原来的类型。

Generics provide strong typing, meaning for example that it is an error to push an int onto a stack of Customer objects. Just as a Stack<int> is restricted to operate only on int values, so is Stack<Customer> restricted to Customer objects, and the compiler will report errors on the last two lines of the following example:

泛型提供了强大的类型能力,对这个例子中而言,压入一个intCustomer对象的栈上会产生一个错误。就像是一个Stack<int>被限制为只操作int值,而Stack<Customer>被限制在Customer对象上,编译器将会在下面例子中的后两行上报告错误:


Stack<Customer> stack = new Stack<Customer>();
stack.Push(
new Customer());
Customer c 
= stack.Pop();
stack.Push(
3); // Type mismatch error
int x = stack.Pop(); // Type mismatch error

 

It was a breif introduction to generics that will be included in the next version of C# (V 2.0) . which is available now on its beta version with Visual C# 2005 Express Edition Beta 1.

这是一个将会包含在下一个C#版本(V2.0)中的泛型的简明介绍,在Visual C# 2005 Express Edition Beta 1这个测试版本已经可以使用泛型了。

Reference:-
http://msdn.microsoft.com/vcsharp/team/language/default.aspx


原文:http://www.c-sharpcorner.com/Code/2004/Oct/GenericsinCSharp.asp
posted on 2004-11-07 14:51  小新0574  阅读(2129)  评论(7编辑  收藏  举报