Общие сведения об универсальных шаблонах



· Используйте универсальные типы для достижения максимального уровня повторного использования кода, безопасности типа и производительности.

· Наиболее частым случаем использования универсальных шаблонов является создание классов коллекции.

· Библиотека классов платформы .NET Framework содержит несколько новых универсальных классов коллекций в пространстве имен System.Collections.Generic. Их следует использовать по мере возможности вместо таких классов как ArrayList в пространстве имен System.Collections.

· Можно создавать собственные универсальные интерфейсы, классы, методы, события и делегаты.

· Доступ универсальных классов к методам можно ограничить определенными типами данных.

· Сведения о типах, используемых в универсальном типе данных, можно получить во время выполнения путем отражения.

 


Introduction to Generics

Generic classes and methods combine reusability, type safety and efficiency in a way that their non-generic counterparts cannot. Generics are most frequently used with collections and the methods that operate on them. Version 2.0 of the .NET Framework class library provides a new namespace, System.Collections.Generic, which contains several new generic-based collection classes. It is recommended that all applications that target Version 2.0 use the new generic collection classes instead of the older non-generic counterparts such as ArrayList.

Of course, you can also create custom generic types and methods to provide your own generalized solutions and design patterns that are type-safe and efficient. The following code example shows a simple generic linked-list class for demonstration purposes. (In most cases, you should use the List<(Of <(T>)>) class provided by the .NET Framework class library instead of creating your own.) The type parameter T is used in several locations where a concrete type would ordinarily be used to indicate the type of the item stored in the list. It is used in the following ways:

· As the type of a method parameter in the AddHead method.

· As the return type of the public method GetNext and the Data property in the nested Node class.

· As the type of the private member data in the nested class.

Note that T is available to the nested Node class. When GenericList<T> is instantiated with a concrete type, for example as a GenericList<int>, each occurrence of T will be replaced with int.

 


Введение в универсальные шаблоны

Способ, которым универсальные классы и методы сочетают возможность многократного использования, строгую типизацию и эффективность, отличается от способа, используемого их не универсальными аналогами. Чаще всего универсальные шаблоны используются с функционирующими с ними коллекциями и методами. Библиотека классов в платформе .NET Framework версии 2.0 предоставляет новое пространство имен, System.Collections.Generic, содержащее несколько новых универсальных классов коллекций. Во всех приложениях, предназначенных для выполнения в .NET Framework 2.0 и более поздней версии, вместо старых нестандартных аналогов, таких как ArrayList, рекомендуется использовать новые универсальные классы коллекций.

Разумеется, чтобы получить собственные строго типизированные и эффективные обобщенные решения и шаблоны разработки, можно создать пользовательские универсальные типы и методы. В следующем примере кода в демонстрационных целях показан простой универсальный класс, реализующий связанный список. (В большинстве случаев следует использовать класс List<(Of <<T>>)>, предоставленный библиотекой классов платформы .NET Framework, а не создавать собственный.) Параметр-тип T используется в нескольких местах, где конкретный тип обычно использовался бы для указания типа элемента, хранящегося в списке. Его можно использовать следующим образом:

· в качестве типа параметра метода в методе AddHead;

· в качестве возвращаемого типа свойства GetNext и Data открытого метода во вложенном классе Node;

· в качестве типа данных закрытого члена во вложенном классе.

Обратите внимание, что T доступен для вложенного класса Node. Когда будет создан GenericList<T> с конкретным типом, например как GenericList<int>, каждое вхождение T будет заменено int.

 


 

// type parameter T in angle brackets

public class GenericList<T>

{

// The nested class is also generic on T.

private class Node

{

   // T used in non-generic constructor.

   public Node(T t)

   {

       next = null;

       data = t;

   }

   private Node next;

   public Node Next

   {

       get { return next; }

       set { next = value; }

   }

   // T as private member data type.

   private T data;

   // T as return type of property.

   public T Data 

   {

       get { return data; }

       set { data = value; }

   }

}

private Node head;

// constructor

public GenericList()

{

   head = null;

}

// T as method parameter type:

public void AddHead(T t)

{

   Node n = new Node(t);

   n.Next = head;

   head = n;

}

public IEnumerator<T> GetEnumerator()

{

   Node current = head;

   while (current != null)

   {

       yield return current.Data;

       current = current.Next;

   }

}

}


 

ß----


The following code example shows how client code uses the generic GenericList<T> class to create a list of integers. Simply by changing the type argument, the following code could easily be modified to create lists of strings or any other custom type:

class TestGenericList { static void Main() {    // int is the type argument    GenericList<int> list = new GenericList<int>();      for (int x = 0; x < 10; x++)    {        list.AddHead(x);    }      foreach (int i in list)    {        System.Console.Write(i + " ");    }    System.Console.WriteLine("\nDone"); } }

 


Следующий пример кода показывает, как клиентский код использует класс GenericList<T> для создания списка целых чисел. Благодаря простому изменению аргумента-типа, следующий код можно легко преобразовать для создания списка строк или любого другого пользовательского типа.

class TestGenericList { static void Main() {    // int is the type argument    GenericList<int> list = new GenericList<int>();      for (int x = 0; x < 10; x++)    {        list.AddHead(x);    }      foreach (int i in list)    {        System.Console.Write(i + " ");    }    System.Console.WriteLine("\nDone"); } }

 


Benefits of Generics

Generics provide the solution to a limitation in earlier versions of the common language runtime and the C# language in which generalization is accomplished by casting types to and from the universal base type Object. By creating a generic class, you can create a collection that is type-safe at compile-time.

The limitations of using non-generic collection classes can be demonstrated by writing a short program that uses the ArrayList collection class from the .NET Framework class library. ArrayList is a highly convenient collection class that can be used without modification to store any reference or value type.

// The .NET Framework 1.1 way to create a list: System.Collections.ArrayList list1 = new System.Collections.ArrayList(); list1.Add(3); list1.Add(105);   System.Collections.ArrayList list2 = new System.Collections.ArrayList(); list2.Add("It is raining in Redmond."); list2.Add("It is snowing in the mountains.");

But this convenience comes at a cost. Any reference or value type that is added to an ArrayList is implicitly upcast to Object. If the items are value types, they must be boxed when they are added to the list, and unboxed when they are retrieved. Both the casting and the boxing and unboxing operations decrease performance; the effect of boxing and unboxing can be very significant in scenarios where you must iterate over large collections.

 


Дата добавления: 2019-03-09; просмотров: 195; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!