Generics

Generics

Generics

➪ Generics


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace cs_schulung
{
  public class MyObjectStack
  {
    private readonly int size;
    private object[] elemente;
    private int zeiger = 0;
    public MyObjectStack(int size)
    {
      this.size = size;
      // Objekte initialisieren
      this.elemente = new object[size];
    }
    public void Push(object element)
    {
      if (zeiger >= this.size) throw new StackOverflowException();
      elemente[zeiger] = element;
      zeiger++;
    }
    public object Pop()
    {
      zeiger--;
      if (zeiger >= 0) return elemente[zeiger];
      else
      {
        zeiger = 0;
        throw new InvalidOperationException("Leerer Stack!!");
      }
    }
    public int Length
    {
      get
      {
        return this.zeiger;
      }
    }
  }
  /* Nachteil der Klasse: es können sowohl Referenz- als auch Werttypen auf den Stack
   * geschoben werden. Bei Werttypen müssen diese aber bei Push als Objekt geboxt werden,
   * beim Auslesen erfolgt das Unboxing. Folge: schlechte Performance.
   * Zweiter Nachteil: die Typprüfung erfolgt erst zur Laufzeit.
   * 
   * Alternative: erzeuge Klassen, die auf einen bestimmten Datentyp spezialisiert sind,
   * etwa: class MyIntegerStack mit private int[] elemente.
   * Damit erzeugt man aber nur eine lange Liste ähnlicher Klassen, die jeweils nur für
   * einen bestimmten Typ zuständig sind.
   * 
   * Lösung: Die Template-Klasse
  */
  public class MyTemplateStack<T>
  {
    private readonly int size;
    private T[] elemente;
    private int zeiger = 0;
    public MyTemplateStack(int size)
    {
      this.size = size;
      // Objekte initialisieren
      this.elemente = new T[size];
    }
    public void Push(T element)
    {
      if (zeiger >= this.size) throw new StackOverflowException();
      elemente[zeiger] = element;
      zeiger++;
    }
    public T Pop()
    {
      zeiger--;
      if (zeiger >= 0) return elemente[zeiger];
      else
      {
        zeiger = 0;
        // throw new InvalidOperationException("Leerer Stack!!");
        // ODER:
        // return null; // PROBLEMATISCH bei Werttypen
        // Lösung, S. 23
        return default(T);
      }
    }
    public int Length
    {
      get
      {
        return this.zeiger;
      }
    }
  }
  /* Es können auch mehrere Parameter vorgegeben werden,
   * z.B. public class Dictionary<K, V>{...}
   * mit dem Aufruf Dictionary<int, MyClass> d = new Dictionary<int, MyClass>();
   * vgl. S. 23
  */
  /* Generische Klassen lassen sich auch vererben, S. 27ff */
  class MySubTemplate<T> : MyTemplateStack<T>
  {
    public MySubTemplate(int size)
      : base(size)
    {
    }
  }
  public class wgGenerics
  {
    static void Stacktest1()
    {
      MyObjectStack s = new MyObjectStack(2);
      s.Push(33);
      s.Push(44);
      //Console.WriteLine(s.Pop());
      //Console.WriteLine(s.Pop());
      for (int i = s.Length; i >= 1; i--)
      {
        Console.WriteLine(s.Pop());
      }
      // Caste den zweiten Wert als string: FEHLER!
      //string str = (string)s.Pop();
      //Console.WriteLine(str);      
    }
    static void Stacktest2()
    {
      MyTemplateStack<int> s = new MyTemplateStack<int>(2);
      s.Push(33);
      s.Push(44);
      for (int i = s.Length; i >= 1; i--)
      {
        Console.WriteLine(s.Pop());
      }
      // default (T):
      Console.WriteLine(s.Pop());
      // Cast-Fehler schon beim Compileraufruf
      //string str = (string)s.Pop();
      //Console.WriteLine(str); 
    }
    // Nicht nur Klassen, auch Methoden können generisch sein:    
    static void Ausgeben<T>(T x)
    {
      Console.WriteLine(x);
    }
    /*YIELD, S. 30 ff; die Methode GetList() sorgt für Bereitstellung der Objekte*/
    static IEnumerable<int> GetList()
    {
      for (int i = 0; i < 11; i++)
      {
        if (i % 2 == 0) yield return i;
      }
    }
    static void YIELDDemo()
    {
      foreach (int y in GetList())
      {
        Console.WriteLine(y);
      }
    }
    /*NULLABLE Types, 
     * Nur relevant bei Werttypen (Referenztypen können grundsätzlich null sein).
     * Problembeispiel Datenbankabfragen: 
     * Spalten sind vom Typ Integer deklariert,
     * enthalten aber keinen Inhalt.
     */
    static void NULLABLETest()
    {
      Nullable<int> x = 1957;
      Nullable<int> y = null;
      // andere Syntax: ? macht aus Datentyp einen null-fähigen typ
      int? a = 1961;
      int? b = null;
      Console.WriteLine(x);
      Console.WriteLine(y);
      Console.WriteLine(a);
      Console.WriteLine(b);
      b = x;
      Console.WriteLine(b);
      y = a;
      Console.WriteLine(a);
    }
    public static void Genericdemo()
    {
      Stacktest1(); Striche();
      Stacktest2(); Striche();
      Ausgeben<int>(19); Striche();
      Ausgeben<double>(19.57); Striche();
      YIELDDemo(); Striche();
      NULLABLETest();
      Striche();
    }
    static void Striche()
    {
      for (int i = 0; i < 45; i++) Console.Write("=");
      Console.WriteLine();
    }
  }
}

wg / 11. Mai 2018



Fragen? Anmerkungen? Tipps?

Bitte nehmen Sie Kontakt zu mir auf.






Vielen Dank für Ihr Interesse an meiner Arbeit.


V.i.S.d.P.: Wilfried Grupe * Klus 6 * 37643 Negenborn

☎ 0151. 750 360 61 * eMail: info10@wilfried-grupe.de

www.wilfried-grupe.de/cs_Generics.html