2012-12-24 26 views
11

Mögliche Duplizieren:
Arithmetic operator overloading for a generic class in C#Betreiber mit Generika Überlastung

Hier ist der Code für die generische Klasse i erstellt haben die komplexe Zahl hinzuzufügen Betreiber zu überlasten.

public class Complex<T> 
{ 
    public T _a, _b; 
    public Complex(T i, T j) 
    { 
     _a = i; 
     _b = j; 
    } 
    public static Complex<T> operator +(Complex<T> i, Complex<T> j) 
    { 
     return new Complex<T>(i._a + j._a, i._b + j._b); 
    } 
} 

, während sie mit dieser Arbeit i einen Fehler erhalten haben,

Error: Operator '+' cannot be applied to operands of type 'T' and 'T' 

kann jemand vorschlagen, mir den Weg i Betreiber Überlastung mit Generika verwenden kann?

+1

http://StackOverflow.com/Questions/756954/arithmetic-Operator-overloading-for-a-generic-Class-in- c-sharp – Habib

+0

und auch: http://stackoverflow.com/questions/147646/solution-for-overplaned-operator-constraint-in-net-generics Nicht in der Lage, Werttypen mit Überlastung des Operators zu definieren, ist eine schwerwiegende Einschränkung von C# . Es gibt einfach keine befriedigende Arbeit zur Verfügung. – citykid

+0

Dies sollte nicht in erster Linie generisch sein. Machen Sie nur ein generisches, wenn es sinnvoll ist ** ** ** dort einzutippen; Deshalb heißen sie * Generika *. –

Antwort

22

Das Problem ist der Compiler kann nicht wissen, ob + Operator auf T angewendet werden kann. Leider gibt es keine Möglichkeit, die Einschränkung T als numerischen Typ in C# festzulegen.

Allerdings könnten Sie in der Lage sein, dies mit Hilfe der dynamischen Laufzeit umgehen:

public class Complex<T> where T : struct 
{ 
    public T _a, _b; 
    public Complex(T i, T j) 
    { 
     _a = i; 
     _b = j; 
    } 
    public static Complex<T> operator +(Complex<T> i, Complex<T> j) 
    { 
     return new Complex<T>(Sum(i._a, j._a), Sum(i._b, j._b)); 
    } 

    private static T Sum(T a, T b) 
    { 
     return (dynamic)a + (dynamic)b; 
    } 
} 
+0

Wow. Ich habe diese Frage viele Male gesehen, aber ich habe diese Antwort nie gesehen. Ich habe in der Vergangenheit wieder Op-Codes ausgegeben, um das zu tun, was die (dynamische) Besetzung zu tun scheint. Interessant. – ja72

0

Sie können zwei generische Objekttypen nicht summieren; In der statischen Funktion versucht man, zwei Elemente vom Typ T i._a und j._a. hinzuzufügen, aber T kann von jedem Typ sein.

was versuchen Sie?

2

Wenn Sie betrügen wollen, müssen Sie sie vorübergehend als dynamic Typ markieren und damit die Laufzeit zu bestimmen, wie es zu tun. Solange der Typ T, den Sie verwenden, den Operator + definiert, funktioniert es. Das bedeutet, dass es sowohl für Zahlen als auch für Strings oder für einen beliebigen Typ (benutzerdefiniert oder nicht) funktioniert. nicht sicher, ob das Ihre Absicht für Complex oder nicht ist. Wenn kein Operator + vorhanden ist, wird eine Ausnahme zur Laufzeit ausgelöst. Es gibt keine Möglichkeit, die Kompilierzeit dafür zu überprüfen.

public class Complex<T> 
{ 
    public T _a, _b; 
    public Complex(T i, T j) 
    { 
     _a = i; 
     _b = j; 
    } 
    public static Complex<T> operator +(Complex<T> i, Complex<T> j) 
    { 
     dynamic d_i = i; 
     dynamic d_j = j; 
     return new Complex<T>(d_i._a + d_j._a, d_i._b + d_j._b); 
    } 
} 

Verwendungsbeispiel mit Strings:

Complex<string> i = new Complex<string>("Hel", "Wor"); 
Complex<string> j = new Complex<string>("lo ", "ld!"); 

Complex<string> ij = i + j; 

Console.WriteLine(ij._a + ij._b); //Hello World! 
0

Wie oben erwähnt, Sie T einschränken könnte IConvertible und verwenden Sie dann den decimal Typ sein, um die gewünschte mathematische Funktion auszuführen, wie folgt:

public class Complex<T> where T : struct, IConvertible 
{ 
    public T _a, _b; 

    public Complex(T i, T j) 
    { 
     _a = i; 
     _b = j; 
    } 

    public static Complex<T> operator +(Complex<T> i, Complex<T> j) 
    { 
     return new Complex<T>(Sum(i._a, j._a), Sum(i._b, j._b)); 
    } 

    private static T Sum(T a, T b) 
    { 
     return (T)Convert.ChangeType(a.ToDecimal(CultureInfo.CurrentCulture) + b.ToDecimal(CultureInfo.CurrentCulture), typeof(T)); 
    } 
}