程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> C#泛型秘訣(2)

C#泛型秘訣(2)

編輯:關於C#

4.3 獲取泛型的類型

問題

您需要在運行時獲得一個泛型類型實例的Type對象。

解決方案

在使用typeof操作符時提供類型參數;使用類型參數實例化的泛型類型,用GetType()方法。

聲明一個一般類型和一個泛型類型如下:

public class Simple
{
  public Simple()
  {
  }
}

public class SimpleGeneric<T>
{
  public SimpleGeneric()
  {
  }
}

使用typeof操作符和簡單類型的名稱就可以在運行時獲得簡單類型的類型。對於泛型類型來說,在調用typeof時類型參數必須要提供,但是簡單類型實例和泛型類型實例都可以使用相同的方式來調用GetType()。

Simple s = new Simple();
  Type t = typeof(Simple);
  Type alsoT = s.GetType();
  //提供類型參數就才可以獲得類型實例
  Type gtInt = typeof(SimpleGeneric<int>);
  Type gtBool = typeof(SimpleGeneric<bool>);
  Type gtString = typeof(SimpleGeneric<string>);
  // 當有一個泛型類實例時,您也可以使用GetType的舊的方式去調用一個實例。.
  SimpleGeneric<int> sgI = new SimpleGeneric<int>();
Type alsoGT = sgI.GetType();

討論

不能直接獲取泛型類的類型,因為如果不提供一個類型參數,泛型類將沒有類型(參考秘訣4.2獲得更多信息)。只有通過類型參數實例化的泛型類才有Type。

如果您在使用typeof操作符時,只提供泛型類型定義而不提供類型參數,將得到下面的錯誤:

// 這產生一個錯誤:
  // Error 26 Using the generic type 'CSharpRecipes.Generics.SimpleGeneric<T>'
  // requires '1' type arguments
  Type gt = typeof(SimpleGeneric);

閱讀參考

查看秘訣4.2;參考MSDN文檔中的“typeof”主題。

4.4 使用相應的泛型版本替換ArrayList

問題

您希望通過將所有ArrayList對象替換為相應的泛型版本以提高應用程序的效率,並使得代碼更易於使用。當結構體或其他值類型存儲在這些數據結構中時,會導致裝箱/拆箱操作,這時就需要這麼做。

解決方案

使用更有效率的泛型類System.Collections.Generic.List來替換已存在的System.Collection.ArrayList類。

下面是使用System.Collection.ArrayList對象的簡單例子:

public static void UseNonGenericArrayList()
  {
    // 創建一個ArrayList.
    ArrayList numbers = new ArrayList();
    numbers.Add(1); // 導致裝箱操作
    numbers.Add(2); // 導致裝箱操作
    // 顯示ArrayList內的所有整數
    // 每次迭代都導致拆箱操作
    foreach (int i in numbers)
    {
      Console.WriteLine(i);
    }
    numbers.Clear();
}

相同的代碼使用了System.Collections.Generic.List對象

public static void UseGenericList()
  {
    // 創建一個List.
    List<int> numbers = new List<int>();
    numbers.Add(1);
    numbers.Add(2);
    // 顯示List中的所有整數.
    foreach (int i in numbers)
    {
      Console.WriteLine(i);
    }
    numbers.Clear();
}

討論

因為所有的應用程序幾乎都會使用ArrayList,從提升您的應用程序的執行效率開始是一個不錯的選擇。對於應用程序中簡單使用ArrayList的地方來說,這種替代是非常容易的。但有些地方需要注意,例如,泛型List類未實現Icloneable接口而ArrayList實現了它。

表4-1顯示了兩個類中的等價成員。

ArrayList類成員 等價的泛型List類成員 Capacity 屬性 Capacity屬性 Count屬性 Count屬性 IsFixedSize屬性 ((IList)myList).IsFixedSize IsReadOnly屬性 ((IList)myList).IsReadOnly IsSynchronized屬性 ((IList)myList).IsSynchronized Item屬性 Item屬性 SyncRoot屬性 ((IList)myList).SyncRoot Adapter 靜態方法 N/A Add 方法 Add方法 AddRange方法 AddRange方法 N/A AsReadOnly方法 BinarySearch方法 BinarySearch方法 Clear方法 Clear方法 Clone方法 Getrange(0, numbers.Count) Contains方法 Contains方法 N/A ConvertAll方法 CopyTo方法 CopyTo方法 N/A Exists方法 N/A Find方法 N/A FindAll方法 N/A FindIndex方法 N/A FindLast方法 N/A FindLastIndex方法 N/A ForEach方法 FixedSize 靜態方法 N/A Getrange方法 Getrange方法 IndexOf方法 IndexOf方法 Insert方法 Insert方法 InsertRange方法 InsertRange方法 LastIndexOf方法 LastIndexOf方法 ReadOnly 靜態方法 AsReadOnly方法 Remove方法 Remove方法 N/A RemoveAll方法 RemoveAt方法 RemoveAt方法 RemoveRange方法 RemoveRange方法 Repeat 靜態方法 使用for循環和Add方法 Reverse方法 Reverse方法 SetRange方法 InsertRange方法 Sort方法 Sort方法 Synchronized 靜態方法 lock(myList.SyncRoot) {…} ToArray方法 ToArray方法 N/A trimExcess方法 TRimToSize方法 trimToSize方法 N/A trueForAll方法

表4-1中的幾個ArrayList的成員和泛型List的成員並非一一對應。從屬性開始說,只有Capacity,Count和Item屬性兩個類中都存在。為了彌補List類中的幾個缺失的屬性,可以把它顯式轉換為Ilist接口。下面的代碼演示了如何使用這些顯式轉換以獲得缺失的屬性。

List<int> numbers = new List<int>();
  Console.WriteLine(((IList)numbers).IsReadOnly);
  Console.WriteLine(((IList)numbers).IsFixedSize);
  Console.WriteLine(((IList)numbers).IsSynchronized);
  Console.WriteLine(((IList)numbers).SyncRoot);

注意,由於缺少返回同步版本的泛型List代碼和缺少返回固定尺寸的泛型List代碼,IsFixedSize和IsSynchronized屬性將總是返回false。SyncRoot屬性被調用時將總是返回相同的對象,本質上這個屬性返回this指針。微軟已經決定從所有泛型集合類中去除創建同步成員的功能。做為代替,他們推薦使用lock關鍵字去鎖住整個集合或其他類型的同步對象來滿足您的需要。

靜態的ArrayList.Repeat在泛型List中沒有對應的方法。做為代替,您可以使用下面的泛型方法:

public static void Repeat<T>(List<T> list, T obj, int count)
  {
    if (count < 0)
    {
      throw (new ArgumentException(
          "參數count 必須大於或等於零"));
    }
    for (int index = 0; index < count; index++)
    {
      list.Add(obj);
    }
}

這個泛型方法有三個參數:

list

泛型List對象

obj

將被以指定次數添加進泛型List中的對象

count

把obj添加進泛型類中的次數

因為Clone方法也沒有出現在泛型List類中(因為這個類並沒有實現Icloneable接口),您可以使用泛型List類的GetRange方法做為替代。

List<int> oldList = new List<int>();

// 給oldList添加元素…

List<int> newList = oldList.GetRange(0, oldList.Count);

GetRange方法對List對象中一個范圍的元素執行淺拷貝(跟ArrayList中的Clone方法接近)。在此例中這個范圍是所有元素。

提示:ArrayList默認的初始容量是16個元素,而List<T>的默認初始容量為4個元素。這意味著當添加第17個元素時,List<T>不得不改變尺寸(重新分配內存)3次,而ArrayList只重新分配一次。這一點在評估應用程序性能時需要被考慮。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved