1 / 43

Introduction to .NET Generics

Introduction to .NET Generics. Sam Gentile Chief .NET Architect - Adesso July 20, 2004. Internationally known .NET guy Working with CLR since 1999! INETA Speaker, MVP – C#/.NET Chief .NET Architect, Adesso Systems

albert
Télécharger la présentation

Introduction to .NET Generics

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Introduction to .NET Generics Sam Gentile Chief .NET Architect - Adesso July 20, 2004

  2. Internationally known .NET guy Working with CLR since 1999! INETA Speaker, MVP – C#/.NET Chief .NET Architect, Adesso Systems .NET products and expertise for Microsoft, Groove, NaviSite, BCGI, Pacific MindWorks Designed and implemented Groove Toolkit for Microsoft Visual Studio .NET (JOLT Winner) Who is this Guy?

  3. .NET Writer and Community MSDN Columnist “Beyond Add Reference”, “Using the .NET Framework SDK Interop Tools” WinForms for Managed C++ Programmers, Chris Sells & Sam Gentile, MSDN April 2003 .NET DJ April 2003 Co-author Wrox Visual C++.NET – Interop, COM Interop O’Reilly articles Blog and Contacts Major .NET Blogger at http://samgentile.com/blog/ .NET home at http://www.samgentile.com/ ManagedCode@comcast.net Who is this Guy?

  4. Why and What Are Generics?

  5. The Need for Generics public class List { private object[] elements; private int count; public void Add(object element) { if (count == elements.Length) Resize(count * 2); elements[count++] = element; } public object this[int index] { get { return elements[index]; } set { elements[index] = value; } } public int Count { get { return count; } } } public class List<ItemType> { private ItemType[] elements; private int count; public void Add(ItemType element) { if (count == elements.Length) Resize(count * 2); elements[count++] = element; } public ItemType this[int index] { get { return elements[index]; } set { elements[index] = value; } } public int Count { get { return count; } } } List intList = new List(); intList.Add(1); intList.Add(2); intList.Add("Three"); int i = (int)intList[0]; List intList = new List(); intList.Add(1); // Argument is boxed intList.Add(2); // Argument is boxed intList.Add("Three"); // Should be an error int i = (int)intList[0]; // Cast required List<int> intList = new List<int>(); intList.Add(1); // No boxing intList.Add(2); // No boxing intList.Add("Three"); // Compile-time error int i = intList[0]; // No cast required

  6. The Need - Unnecessary Boxing and Unboxing

  7. Compile-time type checking By using ArrayList, we lost type information! Specify & check type at compile time Binary code reuse Reuse same code with multiple types Generic code generated at run-time! CLR reuses most of JIT code Reduced code bloat Performance No boxing and unboxing Clarity Why Generics?

  8. Simply, Ability to add parameters to your types Formally: Parameterized polymorphism of classes, structs, interfaces, delegates & methods by type of data Facility for creating types that have type parameters Looks and feels like template mechanism in C++, Ada, Java but… Don’t suffer their complications, have constraints Operate at runtime versus compile time VB, C#, MC++ produce & consume generics Framework also provides bunch of generic collection classes i.e. System.Collections.Generic.List What are Generics?

  9. Given example public class Stack<T> { T[] items; int countItems; public void Push(T item) { ... } public T Pop {....} } Type parameter is T between <> Type parameter formal placeholder for type to be supplied later In Stack<int> stack = new Stack<int>(); int is type argument Stack<int> type called constructed type Process of creating specific constructed type from generic type called generic type instantiation Also called the instance type Terms and Definitions

  10. Generics may have any # of type parameters Class Node<K, T> { public Node(K key, T item, Node<K, T>nextNode {….} private K Key; private T Item; private Node<k, T> NextNode; } Must then instantiate with the # of parameters Applying Generics

  11. VB Generics in VB Public Class List(Of ItemType)      Private elements() As ItemType      Private elementcount As Integer      Public Sub Add(ByVal element As ItemType)           If elementcount = elements.Length Then Resize(elementcount * 2)           elements(elementcount) = element           count += 1      End Sub      Public Default Property Item(ByVal index As Integer) As ItemType           Get               Return elements(index)           End Get           Set (ByVal Value As ItemType)              elements(index) = Value           End Set      End Property      Public ReadOnly Property Count As Integer           Get               Return elementcount           End Get      End Property End Class Dim intList As New List(Of Integer) intList.Add(1)           ‘ No boxing intList.Add(2)           ‘ No boxing intList.Add(“3")     ‘ Compile-time error Dim i As Integer = intList(0)  ’ No cast required

  12. C++ Generics in C++ generic<typename T> public ref class List {    array<T>^ elements;    int count; public:    void Add(T element) {       if (count == elements->Length) Resize(count * 2);       elements[count++] = element;    }    property T default [int index] { T get() { return elements[index]; }       void set(T value) { elements[index] = value; }    }    property int Count {       int get() { return count; }    } }; List<int>^ intList = gcnew List<int>(); intList->Add(1);           // No boxing intList->Add(2);           // No boxing intList->Add(“3");     // Compile-time error int i = intList[0];        // No cast required

  13. Type parameters can be applied to Class, struct, interface, and delegate types Applying Generics class Dictionary<K,V> {…} struct HashBucket<K,V> {…} interface IComparer<T> {…} delegate R Function<A,R>(A arg); Dictionary<string,Customer> customerLookupTable; Dictionary<string,List<Order>> orderLookupTable; Dictionary<string,int> wordCount;

  14. Applying Generics • Type parameters can be applied to • Class, struct, interface, and delegate types • Methods string[] names = Utils.CreateArray<string>(3); names[0] = "Jones"; names[1] = "Anderson"; names[2] = "Williams"; Utils.SortArray(names); class Utils{ public static T[] CreateArray<T>(int size) { return new T[size]; } public static void SortArray<T>(T[] array) { … } }

  15. Demo! Stack Class

  16. Generics in a struct public struct Point<T> { public T x; public T y; } Point<int> point; point.X = 4; point.Y = 2; Point<double> point; point.X = 1.2; point.Y = 4.4; Same rules as generic classes Applying Generics

  17. public interface ICalculator<T> { T Add(T param1, T param2); } public class SamCalculator : ICalculator<int> { public int Add(int arg1, int ar2) { return arg1 + arg2; } } Interface declared with type parameters = a generic interface declaration Generic Interfaces

  18. May be declared inside class, struct or interface def, which itself may be generic or non-generic Example of Non-Generic class: public class MyClass { public void MyMethod<T>(T t) {…} } MyClass foo = new MyClass(); Foo.MyMethod<int>(3); Example with class generic: Public delegate bool Test<T>(T item) Public class Finder { public static T Find<T>(T[] items, Test<T> test) { foreach(T item in items) { if (test(item) return item;} throw new InvalidOperationException(“Item not found”); } Generic Methods

  19. Constraints

  20. Big problem with C++ templates: try to use method, property of type parameter that it does not implement Causes very confusing unrelated error messages! Unacceptable in CLR as it would break type safety Rule: Generic code is only valid if it will work for every possible constructed instance of the generic Examples: public class Math { public T Min<T>(T item1, T item2) { if (item1 < item2) return item1; return item2; } } What if type T does not have a less-than operator?? Constraints

  21. public class LinkedList<K, T> { T Find(K key) { …. if (current.Key == key) // will not compile Compiler does not know if K (type supplied) supports == operator Could use IComparable.CompareTo() Does not compile either as compiler has no way of knowing if K derived from IComparable Explicit cast causes exception if not derived and boxing if is In CLR, can tell compiler which constraints a specified type must obey in order to be used instead of generic type parameters Two kinds Derivation constraints Constructor constraints Constraints

  22. Where reserved word to define a constraint Use where on generic type parameter followed by derivation colon indicating generic type parameter implements particular interface public class LinkedList<K, T> where K : IComparable Does not eliminate boxing penalty Overcome by new generic interface IComparable<T> in System.Collections.Generics Constrain plus new interface eliminates boxing penalty: public class LinkedList<K, T> where K : IComparable<K> Derivation Constraints

  23. All constraints must appear after actual derivation list of generic class Ex: If LinkedList<T> derives from IEnumerable<T>, put where keyword after it: public class LinkedList<K,T> : IEnumerable<T> where K : IComparable<K> In general, only define constraint at level you need it Can provide constraints for every generic type parameter public class LinkedList<K, T> where K : IComparable<K> where T : IClonable Derivation Constraints

  24. Suppose want to instantiate new generic object inside generic class C# compiler doesn’t know whether specific type you are going to use has matching public default constructor Will not compile Constructor constraint makes possible for generic code to create instances of type specified by constraining type args to types that implement public default constructor Only default or parameterless constructors supported Constructor Constraints

  25. class Node<K, T> where T : new() { public Node() { Key = default(k); Item = new T(); NextNode = null; } } Constructor Constraints

  26. A variable of a type-parameter type may only be implicitly cast to and from its base constraint type or bases Means If type parameter T has no constraints can only be cast to and from System.Object static void Foo<T>(T arg) { Object o = arg; T temp = (T) o; Int32 num; num = (Int32) temp; // Compiler error num = (Int32)(Object) temp;// Compiles, but throws InvalidCast // Exception at runtime if T!=Int temp = (T) 5; // Compiler Error temp = (T) (Object) 5; // Compiles, but throws Generics and Casting

  27. Recall foreach is used to iterate over elements of an enumerable collection To be enumerable, collection must have parameterless GetEnumerator method returning an enumerator C# 2.0 simplifies creating enumerators with Iterators Iterator is statement block that yields an ordered seq. of values Distinguished from normal statement block by presence of one or more yield statements The yield return statement produces next value of iteration The yield break statement indicates iteration complete Iterator may be used as body of function member as long as return type of function member one of enumerator interfaces or enumerable interfaces Iterators

  28. The enumerator interfaces are System.Collections.IEnumerator and types constructed from System.Collections.Generic.IEnumerator<T> The enumerable interfaces are System.Collections.IEnumerable and types constructed from System.Collections.Generic.IEnumerable<T> Note! Iterator not kind of member but means of implementing a function member Member implemented via Iterator may be overridden or overloaded by other members that may or may not be implemented via Iterators Using System.Collections.Generic; Public class Stack<T> : IEnumerable<T> { T[] items; int count; public void Push(T data) {….} public IEnumerator<T> GetEnumerator() { for (int I = count – 1; I >= 0; --i) { yield return items[i]; } Iterators

  29. Demo! Constraints, Iterators in a Linked List Class

  30. Using Generics in the BCL

  31. System.Collections.Generic classes List<T> LinkedList<T> // new in Beta1! Dictionary<K, V> // equivalent to non-generic HashTable Stack<T> Queue<T> System.Collections.Generic interfaces IList<T> // replacement for IList IDictionary<K, V> // replacement for IDictionary ICollection<T> // replacement for ICollection IEnumerable<T> // replacement for IEnumerable IEnumerator<T> // replacement for IEnumerator IComparable<T> // replacement for IComparable IComparer<T> // replacement for IComparer Enhancing the Base LibraryGeneric Collections

  32. All generic collections implement generic IEnumerable<T> interface IEnumerable<T> provides access to IEnumerator<T> Iterators interface, for abstracted iterations over collections (Think C++ STL Iterators) Public interface IEnumerable<T> { IEnumerator<T> GetEnumerator(); } Public interface IEnumerator<T> : IDisposable { T Current {get;} bool MoveNext(); } Using Generics in the BCL

  33. Provides nullability for any type Useful in many situations such as nullable columns in database Struct that combines a T and a bool Conversions between T and Nullable<T> Conversion from null literal to Nullable<T> System.Nullable<T> Nullable<int> x = 123; Nullable<int> y = null; int i = (int)x; int j = x.Value; if (x.HasValue) Console.WriteLine(x.Value);

  34. Demo! Using the New Generic BCL Collection Classes

  35. CLR Implementation of Generics

  36. Generics not same as C++ templates! C++ templates With many C++ compilers, compiler does not even compile until use with type When type specified, compiler inserts inline – global find and replace! Compiler inserts every time even if already specified that type Up to linker to resolve if can Code bloating Cryptic error messages! Differences with C++ Templates

  37. Research & Prototype with Gyro in Rotor After paper in 2001 Design takes into account dynamic loading & code generation of CLR Generics have native support in IL and CLR Thus a multi-language design Design Features “Just-in-time” type specialization Code and representation sharing No boxing Efficient support of run-time types Generics Implementation in CLR

  38. Support for Polymorphism in IL Some new types added to IL type system New polymorphic forms of IL declarations for classes, interfaces, structs, methods Some new IL instructions and generalizations of existing ones Generics Implementation in CLR

  39. Non-Generic Stack IL

  40. .method public hidebysig specialname rtspecialname instance void.ctor() cil managed { // Code Size: 29 byte(s) .maxstack 8 L_0000: ldarg.0 L_0001: call instance voidobject::.ctor() L_0006: nop L_0007: ldarg.0 L_0008: ldc.i4.s 10 L_000a: newarr !0 L_000f: stfld !0[] Stack!1<!0>::store L_0014: ldarg.0 L_0015: ldc.i4.0 L_0016: stfld int32Stack!1<!0>::size L_001b: nop L_001c: ret } Generic Stack IL

  41. Code with generics still compiled to IL But, IL contains parameters/placeholders for actual specific type Plus metadata contains generic info Depends on whether value or reference type If value type, JIT replaces generic type parameters in IL with specific value + compiles BUT, JIT keeps track of type-specific code already generated If same type, simply returns reference – shared No code bloating! JIT Compilation of Generic IL

  42. The C# Programming Language, Hejlsberg, Wiltamuth & Golde, AW, 2004 “The Design and Implementation of Generics for the .NET Common Language Runtime”, Kennedy and Syme, Microsoft Research http://research.microsoft.com/projects/clrgen/generics.pdf “Introducing Generics in the CLR”, MSDN Magazine, September 2003, http://msdn.microsoft.com/msdnmag/issues/03/09/NET/ “More on Generics in the CLR”, October 2003, http://msdn.microsoft.com/msdnmag/issues/03/10/NET/default.aspx My CLR/Rotor Blog http://samgentile.com/blog/ References

  43. As an INETA member, your User Group gets: Visits from Speaker Bureau members at no charge INETA even pays for the pizza Discounts on software, conferences, subscriptions and more Newsletter, content repository and forums of use to User Group members INETA needs volunteers Benefit your User Group and yourself by getting involved INETA Web Site: www.ineta.org It’s A User Group Thing

More Related