Overview C# Help

Generics are not a completely new construct; similar concepts exist with other languages. For example, C++ templates can be compared to generics. However, there’s a big difference between C++ templates and .NET generics. With C++ templates, the source code of the template is required. when a template is instantiated with a specific type. Contrary to C++ templates, generics are not only a construct of the C# language; generics are defined with the CLR. This makes it possible to instantiate generics with a specific type in Visual Basic even though the generic class was defined with C#.

The following sections look into the advantages and disadvantages of generics, particularly: .

  1. Performance
  2. Type safety
  3.  Binary code reuse
  4.  Code bloat
  5.  Naming guidelines.

Performance

One of the big advantages of generics is performance. In Chapter 10,you will see non-generic and generic collection classes from the namespaces System. Collections and System. Collections. Generic Using value types with non-generic collection classes results in boxing and unboxing when the value type is converted to a reference type add vice versa.

Value types are stored on the stack. Reference types are stored on the heap. C# classes are reference types; structs are value types .. NET makes it easy to convert value types to reference types, and so you can use a value type everywhere an object (which is a reference type) is needed. For example, an int can be assigned to an object. The conversion from a value type to a reference type is known as boxing. Boxing happens ..automatically if a method requires an object as a parameter, and a value type is passed. On the other sit it, a boxed value type call be converted to a value type by using unboxing. With unboxing, the cast operator is required.

The following example shows the Array List class from the namespace System. ColIections. ArrayList stores objects, the Add() method is defined to require an object as a parameter, and so an integer type is boxed. When the values from an ArrayList are read, unboxing occurs when the object is converted to an integer type. This may be obvious with the cast operator that is used to assign the first element of the ArrayList collection to the variable il, but also happens inside the foreach statement where the variable i2 of type int is accessed:

Img

Boxing and unboxing are easy to use, but have a big performance impact, especially when iterating through many items,

Instead of using objects, the List<T> class from the namespace System.Collections .Generic allows you to define the type when it is used. In the example here, the generic type of the Lisc–<T>class is defined as int, so the int type is used inside the class that is generated dynamically from the JIT compiler. Boxing and unboxing no longer happens:

Img

Type Safety

Another feature of generics is type safety. As with the ArrayList class, if objects are used, any type can be added to this collection. This example shows adding an integer, a string, and an object of type MyClass to the collection of type ArrayList:

ArrayList list = new ArrayList();
list.Add(44) ;
list.Add(‘mystring·);
list.Add(new MyClass()

};

Now if this collection is iterated using the following foreach statement, which iterates using integer elements, the compiler accepts this code. However, because not all elements in the collection can be cast to an int, a runtime exception will occur:

foreach (int i in list)
{
Console.WriteLine(i) ;

}

Errors should be detected as early as possible. With the generic class List<T>, the generic type T defines what types are allowed. With a definition of List<int>, only integer types can be added to the collection. The compiler doesn’t compile this code because the Add () method has invalid arguments:

Img

Binary Code Reuse

Generics allow better binary code reuse. A generic class can be defined once and can be instantiated with many different types. Unlike C++ templates, it is not necessary to access the source code.

As an example, here the List<T> class from the namespace System. Collections. Generic is instantiated with an int, a string, and a MyClass type:

Img

Generic types can be defined in one language and used from any other .NET language.

Code Bloat

How much code is created with generics when instantiating them with different specific types?

Because a generic class definition goes into the assembly, instantiating generic classes with specific types doesn’t duplicate these classes in the IL code. However, when the generic classes are compiled by the JIT compiler to native code, a new class for-every specific value type is created. Reference types share all the same implementation of the same native class. This is because with reference types only a 4-byte . memory address (with 32-bit systems) is needed within the generic instantiated class to reference a reference type. Value types are contained within the memory of the generic instantiated class, and because every value type can have different memory requirements, a new class for every value type is instantiated.

Naming Guidelines

If generics are used in the program, it helps when generic types can be distinguished from non-generic types. Here are naming guidelines for generic types:

  1.  Generic type names should be prefixed with the letter T.
  2.  If the generic type can be replaced by any class because there’s no special requirement, and only one generic type is used, the character T is good as a generic type name:
    public class List<T> { }
    public class LinkedList<T> { }
  3. If there’s a special requirement for a generic type (for example, it must implement an interface or derive from a base class), or if two or more generic types are used, descriptive names should be used for the type names:
    public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);
    public delegate TOutput Converter<Tlnput, TOutput>(Tlnput from);
    public class SortedList<TKey, TValue> { }

Posted on October 29, 2015 in Generics

Share the Story

Back to Top
Share This