Delphi-Forum.de Delphi-Library.de
C-Sharp-Forum.de C-Sharp-Library.de
Registrieren Login Suche Hilfe Sitemap
Generics ad absurdum
spacer
Autor Nachricht
thomas_danecker
Hält's aus hier

Beiträge: 2
Dabei seit: 14.03.2006



BeitragVerfasst: Di 14.03.06 16:10  Antworten mit Zitat Beitrag melden
Eine "einfache" Klasse:
ausblenden C#-Quelltext markieren
1:
2:
3:
4:
public class Bar<T>
    where T : Bar<T>
{
}



Dieser code kompiliert einwandfrei doch jeder wird sich die Frage stellen: Wie erstellt man eine Instanz von dieser Klasse?
Schon mal vorweggenommen: Es gibt eine Möglichkeit!


Aber so nicht:

ausblenden C#-Quelltext markieren
1:
Bar<Bar<Bar<Bar.....>>>>



So auch nicht:

ausblenden C#-Quelltext markieren
1:
2:
Type t = typeof(Bar<>);
t.MakeGenericType(t.MakeGenericType(...));



Schon jemand eine Idee?


Man braucht noch etwas Hilfe:

ausblenden C#-Quelltext markieren
1:
2:
3:
class Foo : Bar<Foo>
{
}


So, jetzt gehts:

ausblenden C#-Quelltext markieren
1:
Bar<Foo> bar = new Bar<Foo>();



Wie man sieht kann man sogar die Klasse selbst als generischen Parameter verwenden!

Moderiert von Christian S.: C#-Tags hinzugefügt
Moderiert von Christian S.: Topic aus C# - Die Sprache verschoben am Di 14.03.2006 um 15:36
Private Nachricht sendenPosting in privater Nachricht zitieren
Robert_G
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star

Beiträge: 415
Dabei seit: 06.02.2004
Wohnort: München


Delphi32 (D2005 PE); Chrome/C# (VS2003 E/A, VS2005)
BeitragVerfasst: Di 14.03.06 16:44  Antworten mit Zitat Beitrag melden
thomas_danecker hat folgendes geschrieben:
So, jetzt gehts:
Bar<Foo> bar = new Bar<Foo>();Wie man sieht kann man sogar die Klasse selbst als generischen Parameter verwenden!
Es geht auch einfach so: Foo foo = new Foo();
Das ganze nennt sich rekursive naked constraint und ist vital wenn man die Klasse selbst als Typenparameter einer anderen Klassen übergeben will/muss.
So kann man interfaces bauen, die zwar poperties besitzen, die durch dieses Interface festgelegt sind, aber eine Klasse sein können, die das interface implementiert:
ausblenden volle Höhe C#-Quelltext markieren
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
interface IMiep<T, D> 
  where T: IMiep<T, D>
  where D: IMööp<D, T>, new()
{
  D Mööp { get; }
}

interface IMööp<D, T>
  where D: IMööp<D, T> 
  where T: IMiep<T, D> 
{
  T Miep{ get; set; }
}


class Miep<T, D> : IMiep<T, D>
  where T: Miep<T, D>
  where D: Mööp<D, T>, new()
{
  D mööp = new D();

  public D Mööp
  {
    get{return mööp;}
  }

  public Miep()
  {
    mööp.Miep = this;
  }
}

class Mööp<D, T> : IMööp<D, T>
  where D: Mööp<D, T> 
  where T: Miep<T, D> 
{
  T miep;
  public T Miep
  {
    get{return miep;}
    set{miep = value;}
  }
}

class TestMiep : Miep<TestMiep, TestMööp>
{}
class TestMööp : Mööp<TestMööp, TestMiep>
{}

Sowas baut man sich tief in generische Libs mit einem dritten Typen, der dann in den jeweiligen Klassen den Wert hält. Auf die Art kann man mit einem Satz Code plötzlich zig Klassen bedienen. Öffentlich sichtbar macht solch kranke Konstrukte eigentlich nie. ;)
Der Vorteil liegt darin, dass dir Typenparameter keine Laufzeitkosten bescheren, alles wird zur Compile/JIT-Zeit aufgelöst.
Nicht alles was auf den ersten Blick sinnlos erscheint muss auch tatsächlich sinnlos sein. Gerade für dynamisch generierten Code ist sowas ein echter Lebensretter...

Das klassiche Beispiel dürfte IComparable<T>, IEquatable<T>,... sein.
Ohne diese rekursiven constraints müsste man einen int auf object boxen um ihn in generics vergleichen zu können. Mit geht plötzlich das:
ausblenden C#-Quelltext markieren
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
class SomeList<T> : List<T>
  where T: IEquatable<T>;
{
  public IEnumerable<T> FindMatching(T value)
  {
     foreach(T item in this)
     {
       if (item.Equals(value))
         yield return item;
     }
  }
}
Private Nachricht sendenPosting in privater Nachricht zitieren
Werbung ausblenden? Dann registriere Dich kostenlos. Weitere Gründe für eine Registrierung.


Werbung ausblenden? Dann registriere Dich kostenlos. Weitere Gründe für eine Registrierung.
Beiträge vom vorherigen Thema anzeigen:   
home home