c#v2.0 擴展特性(2)

 

 Generic type instantiations<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

範型實例化

Similar to a non-generic type, the compiled representation of a generic type is intermediate language (IL) instructions and metadata. The representation of the generic type of course also encodes the existence and use of type parameters.

和非泛型類似,泛型被編譯後表示成中間代碼指令和元數據。泛型的表示當然也是將已有的和使用的類型參數編碼

 

The first time an application creates an instance of a constructed generic type, such as Stack<int>, the just-in-time (JIT) compiler of the .NET Common Language Runtime converts the generic IL and metadata to native code, substituting actual types for type parameters in the process. Subsequent references to that constructed generic type then use the same native code. The process of creating a specific constructed type from a generic type is known as a generic type instantiation.

當應用程序第一次創建一個新的被構造的泛型,例如Stack<int>.Net公共運行時的JIT將泛型的中間代碼和元數據轉化成本地代碼,在進程中用真實類型取代類型參數。後來引用已經被構建的泛型就運行本地代碼。根據指定的構建類型來創建泛型被稱作泛型的實例化。

 

The .NET Common Language Runtime creates a specialized copy of the native code for each generic type instantiation with a value type, but shares a single copy of the native code for all reference types (since, at the native code level, references are just pointers with the same representation).

.Net 公共語言運行時爲每個值類型的泛型創建一個專門的本地代碼拷貝。但會爲所有引用類型共享一個單獨的本地代碼拷貝。(因爲,在本地代碼層次,引用和指針就是同一表示)

 

19.1.2 Constraints

約束

 

Commonly, a generic class will do more than just store data based on a type parameter. Often, the generic class will want to invoke methods on objects whose type is given by a type parameter. For example, an Add method in a Dictionary<K,V> class might need to compare keys using a CompareTo method:

一般來說,一個泛型類不僅可以存儲建立在類型參數上的數據,還能做更多。通常,泛型類會嘗試調用被指定類型對象上的方法。舉例說,在Dictionary<K,V>類中一個Add方法可能需要通過CompareTo方法比較關鍵字。

public class Dictionary<K,V>
{
public void Add(K key, V value)
{
     ...

     if (key.CompareTo(x) < 0) {...}    // Error, no CompareTo method
     ...
}
}

Since the type argument specified for K could be any type, the only members that can be assumed to exist on the key parameter are those declared by type object, such as Equals, GetHashCode, and ToString; a compile-time error therefore occurs in the example above. It is of course possible to cast the key parameter to a type that contains a CompareTo method. For example, the key parameter could be cast to IComparable:

然而類型參數K可能是任何類型,被假定存在於Key參數的唯一成員變量是那些object類型所聲明的,比如說 EqualGetHashCodeToString ;上面的代碼將引發一個編譯時錯誤。當然也可以把Key

參數轉化成一個包含CompareTo方法的類型。例如,Key參數可能被轉化成支持IComparable接口

public class Dictionary<K,V>
{
public void Add(K key, V value)
{
     ...

     if (((IComparable)key).CompareTo(x) < 0) {...}
     ...
}
}

While this solution works, it requires a dynamic type check at run-time, which adds overhead. It furthermore defers error reporting to run-time, throwing an InvalidCastException if a key doesn’t implement IComparable.

當以上解決方案運行時,加在上面的代碼要求進行一個運行時的動態類型檢查。而且它在運行時才報告錯誤,並在當key不支持IComparable接口時會拋出一個InvalidCastException.

 

To provide stronger compile-time type checking and reduce type casts, C# permits an optional list of constraints to be supplied for each type parameter. A type parameter constraint specifies a requirement that a type must fulfill in order to be used as an argument for that type parameter. Constraints are declared using the word where, followed by the name of a type parameter, followed by a list of class or interface types, or the constructor constraint new().

爲了提供更強的編譯時類型檢查和減少類型轉換,C#允許一個可選擇的約束列表去提供給每一個類型參數。作爲一個類型參數約束的要求,一個類型參數約束指定一個必須完全履行的類型。約束通過關鍵字where聲明,後面跟上類型參數的名字,再跟上一串類或接口,或是一個約束構造器new()

In order for the Dictionary<K,V> class to ensure that keys always implement IComparable, the class declaration can specify a constraint for the type parameter K:

爲了保證Dictionary<K,V>類的Key支持IComparable接口,類的聲明指定一個類型參數的約束。

 

public class Dictionary<K,V> where K: IComparable
{
public void Add(K key, V value)
{
     ...

     if (key.CompareTo(x) < 0) {...}
     ...
}
}

Given this declaration the compiler will ensure that any type argument supplied for K is a type that implements IComparable. Furthermore, it is no longer necessary to explicitly cast the key parameter to IComparable before calling the CompareTo method; all members of a type given as a constraint for a type parameter are directly available on values of that type parameter type.

指定以後,編譯器將確保任何提供給K的類型參數必須支持IComparable接口。而且,在調用CompareTo 方法前,它不再需要顯式的把Key參數轉化支持IComparable接口。被一個類型參數的約束所給定的所有成員在類型值上直接可見

 

For a given type parameter, it is possible to specify any number of interfaces as constraints, but no more than one class. Each constrained type parameter has a separate where clause. In the example below, the type parameter K has two interface constraints, while the type parameter E has a class constraint and a constructor constraint:

作爲一個給定的類型參數,但對一個類可能會指定任何數量的接口作爲約束。每種約束類型參數有一個Where子句分隔。在下面的例子裏,類型參數K有兩個接口約束,然而類型參數E有一個類約束和一個構建約束。

public class EntityTable<K,E>
where K: IComparable<K>, IPersistable
where E: Entity, new()
{
public void Add(K key, E entity)
{
     ...

     if (key.CompareTo(x) < 0) {...}
     ...
}
}

The constructor constraint, new(), in the example above ensures that a type used as a type argument for E has a public, parameterless constructor, and it permits the generic class to use new E() to create instances of that type.

上面例子中的構建約束new(),確保作爲類型參數E的類型有一個公共的,無參數的構建函數,且它允許泛型類 使用 new E() 去創建該類型的實例。

 

Type parameter constrains should be used with care. While they provide stronger compile-time type checking and in some cases improve performance, they also restrict the possible uses of a generic type. For example, a generic class List<T> might constrain T to implement IComparable such that the list’s Sort method can compare items. However, doing so would preclude use of List<T> for types that don’t implement IComparable, even if the Sort method is never actually called in those cases.

類型參數約束應該小心使用。他們提供更強的編譯時類型檢查並能在某些例子來提高性能,也能約束泛型的使用可能性。舉例說,一個List<T>泛型可能會約束T實現IComparable接口,這樣ListSort方法就可以比較項目。然而,這將使不支持IComparable接口的類型不能使用List<T>,即使Sort方法沒有在案例中被調用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章