6 Stimmen

Wie kann man in einem generischen C#-Typ-Parameter vorschreiben, dass einige Operatoren unterstützt werden?

Mögliches Duplikat:
Definieren Sie eine Generik, die den Operator + implementiert

Ich arbeite gerade an einer C#-Klassenbibliothek zur Implementierung eines Algorithmus. Der Punkt ist, dass ich möchte, dass die Benutzer der Bibliothek in der Lage sein, die Maschine Präzision (einfach oder doppelt) der Algorithmus sollte mit zu wählen, und ich versuche, es mit Generika zu tun. Also, zum Beispiel:

    Algorithm<double> a = new Algorithm<double>();
    /** Some initializations here */
    double result = a.Solve();

o

    Algorithm<float> a = new Algorithm<float>();
    /** Some initializations here */
    float result = a.Solve();

So soll der Typ-Parameter für die generischen Klassen eine Dezimalzahl sein (weil ich im Algorithmus-Code +, *, /, - verwenden muss), aber ich weiß nicht, welche Art von Typ-Beschränkung ich ihm auferlegen soll. Ich habe darüber nachgedacht, eine Schnittstelle mit allen Operatoren zu bauen, aber das ist leider nicht erlaubt. Hat jemand eine Idee?

Ist es andernfalls möglich, in C# etwas Ähnliches zu erhalten wie Schablonen-Spezialisierung in C++?

Dankeschön

Tommaso

7voto

Jon Skeet Punkte 1325502

Im Grunde können Sie das nicht. Das CLR-Typ-System unterstützt diese Art von Einschränkung nicht.

Ich habe schon früher darüber gebloggt, wie wir könnte beschreiben solche Zwänge mit "statische Schnittstellen" aber mir sind keine Pläne bekannt, etwas Ähnliches zu tun.

Sie sollten sich vielleicht die MiscUtil Unterstützung für generische Operatoren die es Ihnen ermöglichen würde verwenden. die Operatoren - aber Sie müssten eine Einschränkung von nur struct oder etwas Ähnliches, was natürlich Dinge ermöglichen würde wie Guid was Sie nicht wollen.

1voto

Guru Punkte 171

Die nächstliegende Übereinstimmung ist der Werttyp constrain.

C# erlaubt nur drei Arten von Constraints

  1. Ableitung Constrain
  2. Konstrukteur
  3. Referenz/Werttyp.

Die vollständige Dokumentation finden Sie auf MSDN:
http://msdn.microsoft.com/en-us/library/ms379564(VS.80).aspx#csharp_generics_topic4

0voto

Zotta Punkte 2318

Sie könnten eine Umgehungslösung verwenden: Definieren Sie eine Methode für jeden Typ, den Sie unterstützen wollen

private static Add(float a, float b) 
{return a+b;}  
private static Add(double a, double b) 
{return a+b;}  
...

und erstellen Sie zur Laufzeit einen Delegaten für den richtigen Delegaten:

MethodInfo addMethod=this.GetType().GetMethod("Add",BindingFlags.NotPublic|Static,null,new Type[2]{typeof(T),typeof(T)},null);  
Func<T,T,T> addFunction=(Func<T,T,T>)Delegate.CreateDelegate(typeof(Func<T,T,T>),addMethod);

0voto

KeithS Punkte 67713

Dies ist in der Regel ein sehr unangenehmer Hack, aber Sie können eine generische "Wrapper"-Klasse für numerische Typen erstellen, die die benötigten Operationen bereitstellt und die Instanziierung mit einem nicht unterstützten Wertetyp (z. B. char) verhindert, und dann angeben, dass der generische Typ-Parameter Ihres Algorithmus die Wrapper-Klasse sein muss.

Mir gefällt die von Floste vorgeschlagene Lösung in jeder Hinsicht, mit Ausnahme der Verdoppelung des Codes. Sie könnten es sogar noch einfacher machen; geben Sie private Methodenüberladungen an, dann eine öffentliche generische Methode, die einfach die private Methode aufruft, und die Laufzeit wählt die richtige aus (stellen Sie sicher, dass Sie eine Catch-All-Funktion einschließen, die eine NotImplementedException auslöst).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X