generics - mit - C#Hinzufügen von zwei generischen Werten



java generics extends (7)

Kann jemand erklären, warum das nicht funktioniert? Ich habe versucht, zwei Werte unabhängig vom numerischen Typ hinzufügen zu können.

public static T Add<T> (T number1, T number2)
{
    return number1 + number2;
}

Wenn ich das kompiliere, erhalte ich den folgenden Fehler:

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

https://src-bin.com


Answer #1

Die hier gegebenen Lösungen funktionieren gut, aber ich dachte, ich würde eine andere hinzufügen, die Ausdrücke verwendet

public static T Add<T>(T a, T b)
{
    // Declare the parameters
    var paramA = Expression.Parameter(typeof(T), "a");
    var paramB = Expression.Parameter(typeof(T), "b");

    // Add the parameters together
    BinaryExpression body = Expression.Add(paramA, paramB);

    // Compile it
    Func<T, T, T> add = Expression.Lambda<Func<T, T, T>>(body, paramA, paramB).Compile();

    // Call it
    return add(a, b);
}

Auf diese Weise erstellen Sie einen Func<T, T, T> , der die Addition durchführt. Die vollständige Erklärung finden Sie in diesem Artikel .


Answer #2

Dies ist ein Problem, das ich gerade hatte, als ich eine generische Methode wollte, die auf beliebigen Listen von Zahlen funktionieren könnte, zum Beispiel:

public T Calculate<T>(IEnumerable<T> numbers);

Die Lösung, die ich fand, war einen Lambda-Ausdruck zu verwenden:

public T Calculate<T>(Func<T, T, T> add, IEnumerable<T> numbers);

Womit du dann anrufen würdest

var sum = this.Calculate((a, b) => a + b, someListOfNumbers);

Offensichtlich können Sie in einigen Fällen auch einfach + innerhalb des Codes anstelle von Lambda-Ausdrücken haben, aber wenn Sie mathematische Operationen auf generische Weise ausführen müssen , war dies die einfachste Sache, die ich finden konnte, kompilieren sicher ist.


Answer #3

Es gibt keine generische Einschränkung, mit der Sie eine Überlastung des Operators erzwingen können. Sie können sich die folgende Bibliothek ansehen. Alternativ können Sie, wenn Sie .NET 4.0 verwenden, das dynamic Schlüsselwort verwenden:

public static T Add<T>(T number1, T number2)
{
    dynamic a = number1;
    dynamic b = number2;
    return a + b;
}

Offensichtlich gilt dies nicht für die Sicherheit bei der Kompilierung, für die Generika bestimmt sind. Die einzige Möglichkeit, die Sicherheit bei der Kompilierungszeit anzuwenden, besteht darin, allgemeine Einschränkungen zu erzwingen. Und für Ihr Szenario ist keine Einschränkung verfügbar. Es ist nur ein Trick, um den Compiler zu betrügen. Wenn der Aufrufer der Add-Methode keine Typen übergibt, die mit dem Operator + arbeiten, gibt der Code zur Laufzeit eine Ausnahme aus.


Answer #4

Typ T ist dem Compiler nicht bekannt, daher kann kein überladener + Operator irgendwo definiert werden ...

Das Beste, was Sie derzeit tun können, ist, Ihre Methode als solche zu deklarieren (da alle numerischen Typen in Double konvertierbar sind):

public static double Add (double number1, double number2)
{
  return number1 + number2;
}

oder wenn Sie sicher sind, dass ein geeigneter + Operator definiert wird:

public static T Add<T>(T number1, T number2)
{
  dynamic dynamic1 = number1;
  dynamic dynamic2 = number2;
  return dynamic1 + dynamic2;
}

Aktualisiert

oder eine Kombination der beiden:

public static T Add<T>(T in1, T in2)
{
    var d1 = Convert.ToDouble(in1);
    var d2 = Convert.ToDouble(in2);
    return (T)(dynamic)(d1 + d2);
}

Answer #5

Weil niemand antwortete, indem er eine Lösung mit einem Objekt zur Verfügung stellte. Deshalb füge ich meine Lösung hinzu. In diesem müssen Sie Ihre generischen Werte in ein Objekt umwandeln.

Also das ist der Arbeitscode:

public static T Add<T>(T number1, T number2)
{
    object a = number1;
    object b = number2;
    return (T)(object)((int)a * (int)b).ToString();
}

Answer #6

Wie Sie aus der Fehlermeldung entnehmen können, kann der Operator '+' nicht angewendet werden. Dies geschieht, weil der Compiler nichts über T-Typ weiß. Es weiß nicht einmal, ob das eine Klasse ist oder nicht.


Answer #7
Since this is generic type without a constraint compiler has no knowledge if the types involved will have '+' overloaded hence the compiler error

These are some workarounds

public static TResult Add<T1, T2, TResult>(T1 left, T2 right, Func<T1, T2, TResult> AddMethod)
{
    return AddMethod(left, right);
}

var finalLabel = Add("something", 3,(a,b) => a + b.ToString());


Below code could let you build same but evaluated at run time so not run time safe

public static T AddExpression<T>(T left, T right)
{
    ParameterExpression leftOperand = Expression.Parameter(typeof(T), "left");
    ParameterExpression rightOperand = Expression.Parameter(typeof(T), "right");
    BinaryExpression body = Expression.Add(leftOperand, rightOperand);
    Expression<Func<T, T, T>> adder = Expression.Lambda<Func<T, T, T>>(
        body, leftOperand, rightOperand);
    Func<T, T, T> theDelegate = adder.Compile();
    return theDelegate(left, right);
}




c#-4.0