codestory

Die Anleitung zu C# Generics

  1. Die Klasse Generics
  2. Die Erbe von der Klasse Generics
  3. Generics Interface
  4. Die Benutzung von Generic mit Exception
  5. Die Methode generics
  6. Die Initialisierung des Objekt Generic
  7. Array Generic

1. Die Klasse Generics

Das folgende Beispiel definiert eine Klasse generics. KeyValue ist eine Klasse generics, die ein Paar Schlüssel und Wert (key/value) enthaltet.
KeyValue.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GenericsTutorial
{
   public class KeyValue<K, V>
   {
       private K key;
       private V value;

       public KeyValue(K key, V value)
       {
           this.key = key;
           this.value = value;
       }
       public K GetKey()
       {
           return key;
       }
       public void SetKey(K key)
       {
           this.key = key;
       }
       public V GetValue()
       {
           return value;
       }
       public void SetValue(V value)
       {
           this.value = value;
       }
   }
}
K, V in die Klasse KeyValue<K,V> werden als der Parameter generics genannt. Es ist ein Typ von Daten. Bei der Benutzung der Klasse sollen Sie den bestimmten Parameter festlegen
Sehen Sie bitte die Beispiel der Benutzung von der Klasse KeyValue.
KeyValueDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GenericsTutorial
{
    public class KeyValueDemo
    { 
        public static void Main(string[] args)
        {
            // Das Objekt KeyValue erstellen.
            // int: Die Telephonenummer  (K = int)
            // string: Der Name des Benutzer.  (V = string).
            KeyValue<int, string> entry = new KeyValue<int, string>(12000111, "Tom");

            // C# versteht das Rückgabetyp als int (K = int).
            int phone = entry.GetKey();

            // C# versteht das Rückgabetyp string (V = string).
            string name = entry.GetValue(); 
            Console.WriteLine("Phone = " + phone + " / name = " + name); 
            Console.Read();
        } 
    } 
}
Das Beispiel durchführen
Phone = 12000111 / name = Tom

2. Die Erbe von der Klasse Generics

Eine Klasse, die verlängert aus einer Klasse, kann das Typ für den Parameter generics festlegen, die generics Parameter halten oder die generics Parameter einfügen
Das Beispiel 1:
PhoneNameEntry.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GenericsTutorial
{ 
    // Diese Klasse verweitert aus der Klasse KeyValue<K,V>
    // Und bestimmt das Typ für 2 Parameter K & V
    // K = int  (die Telephonenummer).
    // V = string   (Der Benutzer).
    public class PhoneNameEntry : KeyValue<int, string>
    { 
        public PhoneNameEntry(int key, string value)
            : base(key, value)
        {

        } 
    } 
}
Zum Beispiel: PhoneNameEntry benutzen:
PhoneNameEntryDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GenericsTutorial
{
    public class PhoneNameEntryDemo
    { 
        public static void Main(string[] args)
        { 
            PhoneNameEntry entry = new PhoneNameEntry(12000111, "Tom");

            // C# versteht das Rückgabetyp als int.
            int phone = entry.GetKey();

            // C# versteht das Rückgabetyp als string.
            string name = entry.GetValue(); 
            Console.WriteLine("Phone = " + phone + " / name = " + name); 
            Console.Read(); 
        } 
    } 
}
Das Beispiel 2
StringAndValueEntry.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GenericsTutorial
{ 
    // Diese Klasse verweitert aus der Klasse  KeyValue<K,V>
    // und bestimmt den Parameter K als String.
    // Den Parameter generic V still halten
    public class StringAndValueEntry<V> : KeyValue<string, V>
    { 
        public StringAndValueEntry(string key, V value)
            : base(key, value)
        {
        } 
    } 
}
Das Beispiel für die Benutzung der Klasse StringAndValueEntry:
StringAndValueEntryDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GenericsTutorial
{
    public class StringAndValueEntryDemo
    { 
        public static void main(String[] args)
        { 
            // (Die Code des Mitarbeier, der Name des Mitarbeiter).
            // V = string (der Name des Mitarbeiter)
            StringAndValueEntry<String> entry = new StringAndValueEntry<String>("E001", "Tom");

            String empNumber = entry.GetKey(); 
            String empName = entry.GetValue(); 
            Console.WriteLine("Emp Number = " + empNumber);
            Console.WriteLine("Emp Name = " + empName); 
            Console.Read(); 
        }
    } 
}
Zum Beispiel 3:
KeyValueInfo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GenericsTutorial
{ 
    // Die Klasse erweitert aus der Klasse  KeyValue<K,V>.
    // Sie hat einen Parameter Generics I.
    public class KeyValueInfo<K, V, I> : KeyValue<K, V>
    { 
        private I info;

        public KeyValueInfo(K key, V value)
            : base(key, value)
        {
        } 
        public KeyValueInfo(K key, V value, I info)
            : base(key, value)
        {
            this.info = info;
        } 
        public I GetInfo()
        {
            return info;
        } 
        public void GetInfo(I info)
        {
            this.info = info;
        } 
    } 
}

3. Generics Interface

Eine Interface mit dem Parameter Generics:
GenericInterface.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GenericsTutorial
{
  public interface GenericInterface<G>
  {
      G DoSomething();
  }
}
Zum Beispiel: eine Klasse zur Durchführung der Interface:
GenericInterfaceImpl.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GenericsTutorial
{
   public class GenericInterfaceImpl<G> : GenericInterface<G>
   {
       private G something;
       public G DoSomething()
       {
           return something;
       }
   }
}

4. Die Benutzung von Generic mit Exception

Sie können eine Exception mit den Parameter Generics definieren
MyException.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GenericsTutorial
{
   class MyException<E> : ApplicationException
   {
   }
}
Generic Exception gültig benutzen:
UsingGenericExceptionValid01.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GenericsTutorial
{
    class UsingGenericExceptionValid01
    { 
        public void SomeMethod()
        {
            try
            {
                // ...
            }
            // Gültig
            catch (MyException<string> e)
            {
                // Hier etwas machen.
            }
            // Gültig
            catch (MyException<int> e)
            {
                // Hier etwas machen              
            }
            catch (Exception e)
            {
            }
        } 
    } 
}
Die gültige Benutzung von Generics Exception
UsingGenericExceptionValid02.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GenericsTutorial
{
    class UsingGenericExceptionValid02<K>
    {
        public void SomeMethod()
        {
            try
            {
                // ... 
            }
            // Gültig
            catch (MyException<string> e)
            {
                // Hier etwas machen
            }
            // Gültig
            catch (MyException<K> e)
            {
                // Hier etwas machen             
            }
            catch (Exception e)
            {
            }
        }
    } 
}
Generics Exception nicht gültig benutzen
UsingGenericExceptionInvalid.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GenericsTutorial
{
    class UsingGenericExceptionInvalid
    {
        public void SomeMethod()
        {
            try
            {
                // ... 
            }
            // Gültig
            catch (MyException<string> e)
            {
                // Hier etwas machen.
            } 
            // Invalid (Unknown parameter K) *********** 
            // catch (MyException<K> e)
            // {
                // ...            
            // }
            catch (Exception e)
            {
            }
        }
    } 
}

5. Die Methode generics

Eine Methode in die Klasse oder Interface kann generified werden
MyUtils.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GenericsTutorial
{
    public class MyUtils
    {
        // <K,V> : informieren, dass die Methode 2 Parameterstyp K,V hat
        // Die Methode gibt das Typ von K zurück.
        public static K GetKey<K, V>(KeyValue<K, V> entry)
        {
            K key = entry.GetKey();
            return key;
        } 
        // <K,V> : informieren, dass die Methode 2 Parameterstyp K,V hat
        // Die Methode gibt das Typ von V zurück
        public static V GetValue<K, V>(KeyValue<K, V> entry)
        {
            V value = entry.GetValue();
            return value;
        } 
        // List<E>: Die Liste enthaltet die Elemente von Typ E.
        // Die Methode gibt das Typ von E zurück.
        public static E GetFirstElement<E>(List<E> list, E defaultValue)
        {
            if (list == null || list.Count == 0)
            {
                return defaultValue;
            }
            E first = list.ElementAt(0);
            return first;
        } 
    } 
}
Zum Beispiel: die Benutzung von der Methode generics:
MyUtilsDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GenericsTutorial
{
    public class MyUtilsDemo
    { 
        public static void Main(string[] args)
        { 
            // K = int: Phone
            // V = string: Name
            KeyValue<int, string> entry1 = new KeyValue<int, String>(12000111, "Tom");
            KeyValue<int, string> entry2 = new KeyValue<int, String>(12000112, "Jerry");

            // (K = int).
            int phone = MyUtils.GetKey(entry1);
            Console.WriteLine("Phone = " + phone);

            // Eine Liste enthaltet die Elemente von Typ KeyValue<int,string>.
            List<KeyValue<int, string>> list = new List<KeyValue<int, string>>();

            // Die Elemente in die Liste einfügen
            list.Add(entry1);
            list.Add(entry2);

            KeyValue<int, string> firstEntry = MyUtils.GetFirstElement(list, null);

            if (firstEntry != null)
            {
                Console.WriteLine("Value = " + firstEntry.GetValue());
            } 
            Console.Read();
        } 
    } 
}
Das Beispiel durchführen
Phone = 12000111
Value = Tom

6. Die Initialisierung des Objekt Generic

Manchmal möchten Sie ein Objekt Generic initialisieren:
public void DoSomething<T>()
{ 
     // Den Constructor Generic initalizieren
     T t = new T(); // Error 
}
Der Grund: der T parameter ist nicht sicher, den Constructor T() zu haben. Deshalb sollen Sie when T : new() einfügen. Sehen Sie das folgende Beispiel
GenericInitializationExample.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GenericsTutorial
{
    class GenericInitializationExample 
    {
        // Das Typ T muss das Typ mit dem Default Constructor sein.
        public void DoSomeThing<T>()
            where T : new()
        {
            T t = new T();
        } 
        // Das Typ K muss den default Constructor haben und erweitert aus der Klasse KeyValue.
        public void ToDoSomeThing<K>()
            where K: KeyValue<K,string>, new( )
        {
            K key = new K();
        }  
        public T DoDefault<T>()
        {
            // null zurückgeben wenn T das Referenz Typ sein (reference type).
            // Oder 0 wenn T das Typ von Nummer  (int, float,..) ist
            return default(T);
        }
    } 
}

7. Array Generic

Im C# können Sie ein Array Generics melden:
// Ein Array initializieren
T[] myArray = new T[10];
GenericArrayExample.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GenericsTutorial
{
   class GenericArrayExample
   {
       public static T[] FilledArray<T>(T value, int count)
       {
           T[] ret = new T[count];
           for (int i = 0; i < count; i++)
           {
               ret[i] = value;
           }
           return ret;
       }
       public static void Main(string[] args)
       {
           string value = "Hello"; 
           string[] filledArray = FilledArray<string>(value, 10);
           foreach (string s in filledArray)
           {
               Console.WriteLine(s);
           }
       }
   }
}