Generische Klasse bei welcher Parameter T von anderer generischer Klasse erben soll

  • C#
  • .NET (FX) 4.5–4.8

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von Bluespide.

    Generische Klasse bei welcher Parameter T von anderer generischer Klasse erben soll

    Ich stehe aktuell etwas auf dem Schlauch und komme nicht so richtig weiter.
    Ich habe eine generische Klasse GenericModule<TValue>:

    C#-Quellcode

    1. public abstract class GenericModule<TValue> where TValue : struct, IComparable
    2. {
    3. public TValue Value { get; set; }
    4. }


    Von dieser Klasse erben verschiedene Module-Varianten:

    C#-Quellcode

    1. public class ModuleVariante1 : GenericModule<int>
    2. {
    3. }
    4. public class ModuleVariante2 : GenericModule<double>
    5. {
    6. }


    Abschließend soll es eine generische Klasse Device<TModule> geben, bei der TModule von GenericModule<> erben soll. Um welche Module-Variante es sich dabei dann handelt soll dementsprechend egal sein.
    Mit typeof funktioniert sowas wie z.B. var type = typeof(GenericModule<>); ja wunderbar.
    Für die Klasse Device<TModule> soll TModule jetzt allerdings auf where TModule : GenericModule<> beschränkt werden.

    C#-Quellcode

    1. public class Device<TModule> where TModule : GenericModule<>
    2. {
    3. }


    Hier bekommen ich dann die Fehlermeldung "CS7003: Unerwartete Verwendung eines ungebundenen generischen Namens.", was ja auch irgendwie verständlich ist
    Lässt sich das Vorhaben so überhaupt umsetzen, oder gibt es für sowas einen andere Ansatz?
    Danke für eure Hilfe.
    Dumm ist der, der dumm ist. Nicht andersrum!
    @Schmittmuthelm Hast Du mal so was probiert (nicht getestet):

    C#-Quellcode

    1. public class ModuleVariante1<T> : GenericModule<T>
    2. {
    3. }
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Dies geht schon mal:

    C#-Quellcode

    1. public class Device<TModule> where TModule : GenericModule<int>
    2. {
    3. }
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @Schmittmuthelm Das musst Du dann einzeln implementieren, wie in Deinem 2. Snippet.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Es klappt erstmal syntaktisch, bedarf aber einer konkreten, doppelten Typangabe. Anbei VB.NET und C#-Code

    VB.NET-Quellcode

    1. Dim Baz As New Bar(Of Foo(Of Integer), Integer)
    2. '…
    3. Friend MustInherit Class Foo(Of T As {Structure, IComparable})
    4. End Class
    5. Friend Class Bar(Of T1 As Foo(Of T2), T2 As {Structure, IComparable})
    6. End Class

    C#-Quellcode

    1. Device<GenericModule<int>, int> Foo = new Device<GenericModule<int>, int>();
    2. //…
    3. public abstract class GenericModule<TValue> where TValue : struct, IComparable {
    4. public TValue Value { get; set; }
    5. }
    6. public class ModuleVariante1 : GenericModule<int> { }
    7. public class ModuleVariante2 : GenericModule<double> { }
    8. public class Device<TModule, Type>
    9. where Type : struct, IComparable
    10. where TModule : GenericModule<Type> {}
    11. }


    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „VaporiZed“ ()

    @VaporiZed So habe ich es aktuell schon umgesetzt, aber irgendwie widerstrebt mir das, den blöden Typ dann immer doppelt zu haben.
    Außerdem Ist da ja trotzdem noch das Problem, dass bei

    C#-Quellcode

    1. public class Device<TModule, Type>
    2. where Type : struct, IComparable
    3. where TModule : GenericModule<Type>
    4. {
    5. public TModule Module { get; set; }
    6. }
    7. //...
    8. Device<GenericModule<int>, int> Foo = new Device<GenericModule<int>, int>();


    Foo.Module immer vom Typ GenericModule<int> ist.
    Dumm ist der, der dumm ist. Nicht andersrum!
    Aber bei normalgenerischen Instanzen musst Du doch auch einen Typ bei der Instanziierung angeben.
    Wenn Du einen Container für diverse Typen brauchst, müsstest Du wahrscheinlich in dem mit object arbeiten und casten. Aber auch irgendwie doof.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Eventuell ein nicht generischen basistypen, zu dem generischen. Kannst aber natürlich nicht auf den spezifischen generische Typen abfragen, brauchst ein gemeinsamen basistypen.

    C#-Quellcode

    1. public interface GenericModule {
    2. public IComparable Value { get; set; }
    3. }
    4. public abstract class GenericModule<TValue> : GenericModule where TValue : struct, IComparable {
    5. public IComparable Value { get; set; }
    6. }
    7. public class ModuleVariante1 : GenericModule<int> {
    8. }
    9. public class ModuleVariante2 : GenericModule<double> {
    10. }
    11. public class Device<T> where T : GenericModule {
    12. }