Jeder elegante Weg, um mit generischen Typen zu arbeiten? [Duplikat]

9

Ich arbeite in einem kleinen Bildungsprojekt, in dem wir eine n -dimensionale Matrix implementieren müssen. Je nach Kontext muss diese Matrix entweder mit unserer eigenen eingebauten ComplexNumber struct oder mit System.Double und für sehr einfache Beispiele mit ganzzahligen Typen (hauptsächlich System.Int32 ) arbeiten.

Aufgrund der Art der Anwendung ist es nicht erforderlich, blitzschnelle Leistung zu implementieren.

Meine erste Idee war daher, ein Matrix<T> zu implementieren, wobei T irgendwie auf "Zahlen" beschränkt werden müsste.

Das offensichtliche Problem dabei ist, dass es momentan in der Sprache keine Möglichkeit gibt, den generischen Typ T mit definierten Operatoren zu beschränken. Außerdem sehe ich keinen einfachen Weg, um T zu vernünftigen Typen zu restrcieren.

Meine Fragen sind:

  1. Kann mir jemand bitte in die Richtung einer eleganten Möglichkeit zeigen, mathematische Operationen mit generischen Typen durchzuführen, die die Leistung nicht zu sehr beeinträchtigen und irgendwie mit eingebauten Typen arbeiten (wenn möglich).

  2. Wenn Eric das jemals liest, taucht dieses Feature (das generische Typen durch definierte Operatoren einschränkt) jemals in hypothetischen zukünftigen Versionen von C # Design-Meetings auf und war jemals kurz davor, es zu machen in die Sprache?

Ich weiß, es ist einfacher und besser, einen ComplexMatrix -Typ zu implementieren und Wrapper um ihn für jeden Matrix- "Untertyp" (doppelt, integral usw.) zu erstellen und die Leistungskosten der Konvertierungen zwischen unserem komplexen Typ und welcher Typ auch immer die Matrixelemente sind. Diese Frage bezieht sich eher auf die Frage, wie jemand ein ähnliches Szenario implementieren könnte.

    
InBetween 14.07.2011, 14:28
quelle

4 Antworten

16
  

Wenn Eric das jemals liest,

Wenn Sie möchten, dass mir etwas zur Kenntnis gebracht wird, versuchen Sie den Kontaktlink in meinem Blog. Oder setze meinen vollständigen Namen in den Text der Frage , damit ich mich selbst finde .

  

kommt diese Funktion (die generische Typen durch definierte Operatoren einschränkt) jemals in hypothetischen zukünftigen Versionen von C # Design-Meetings vor und war sie jemals kurz davor, sie in die Sprache zu bringen?

Tatsächlich ist dies eine häufig angeforderte Funktion. Seit C # 1.0 haben wir Anfragen für diese Art von Dingen bekommen.

Die Funktion erfordert Unterstützung vom CLR-Team, nicht nur die Sprache - es ist die Art von Funktion, die wir in alle unsere Sprachen integrieren möchten, was die Kosten erhöht.

Das CLR-Team hat Interesse an solchen Features bekundet, aber sie haben auch viele konkurrierende Funktionen, die sie ausführen können, und haben nur begrenzten Zeit- und Arbeitsaufwand, um diese Funktionen zu implementieren.

Es gibt zahlreiche Möglichkeiten, wie ein solches Feature implementiert werden könnte. Zum Beispiel könnten wir die Möglichkeit hinzufügen, statische Methoden in Schnittstellen anzugeben:

%Vor%

und dann

%Vor%

Die Idee wäre, dass die Schnittstelle bedeutet, "dass ein Typ, der diese Schnittstelle implementiert, die angegebenen statischen Methoden haben muss". Wir würden dann int automatisch IAddable<int> implementieren und so weiter.

Wie macht man das effizient in einer Welt mit generiertem Code, der von der Laufzeit generiert wird, ist eine offene Frage.

Ich beeile mich hinzuzufügen, dass dies nur eine Skizze einer Idee ist. Es gibt viele Möglichkeiten, diese Art von Funktion zu implementieren. Die Idee "Statik in Schnittstellen" hat eine breitere Anwendung als nur die Mathematik, und das ist für uns attraktiv. Wenn wir zu den enormen Kosten für diese Art von Features gehen, wäre es schön, ein wirklich allgemeines, mächtiges Feature zu haben, anstatt sich nur auf Mathematik zu konzentrieren.

Auf der anderen Seite ist das Perfekte der Feind des Guten; Es könnte besser sein, sich nur auf das mathematische Problem zu konzentrieren und sich nicht für eine teurere allgemeine Lösung zu entscheiden.

Es ist eine anhaltende Debatte. Es ist definitiv auf jedem Radarschirm, aber ich würde es nicht bald erwarten. Die Sprachdesigner arbeiten alle daran, das Feedback aus dem asynchronen CTP durchzugehen.

Wie immer, Erics Gedanken über hypothetische zukünftige Sprachmerkmale hypothetischer unangekündigter zukünftiger Produkte dienen nur Unterhaltungszwecken.

    
Eric Lippert 14.07.2011, 15:27
quelle
2

Der einzige Weg, dieses Ziel halbwegs elegant zu erreichen, ist das Folgende: Lassen Sie den Aufrufer einen Delegaten für die benötigten Operatoren angeben und verwenden Sie diese Delegaten.

z.B.:

%Vor%

Allerdings habe ich keine Ahnung von der Leistung dieses Ansatzes ...

    
Daniel Hilgarth 14.07.2011 14:34
quelle
2

Es hängt von Ihrer Vorstellung ab, was elegant ist. Wenn Ihre Vorstellung von Eleganz in der Lage ist, a+b zu schreiben, wo a und b vom generischen Typ sind, und das wäre meine Vorstellung von elegant, dann kann dies nicht getan werden.

Leider können C # Generika nicht die Eleganz von C ++ Vorlagen für diese Art von Code erreichen.

    
David Heffernan 14.07.2011 14:38
quelle
1

Eine Problemumgehung mit anständiger Leistung (die immer noch hässlich ist) ist die Verwendung einer Struktur, die das gewünschte arithmetische Verhalten kapselt.

Sie definieren zuerst eine Schnittstelle:

%Vor%

Dann implementieren Sie diese Schnittstelle mit struct :

%Vor%

Und schließlich übergeben Sie die Struktur als generischen Parameter in Ihren Typ:

%Vor%

Ich habe es nicht bewertet, aber ich vermute, dass es ziemlich schnell ist, da Generika für jeden Werttyp, der in sie eingegeben wird, spezialisiert werden. Deshalb ist DoubleArithmetic ein struct .

    
CodesInChaos 14.07.2011 18:31
quelle

Tags und Links