Перегрузка оператора дженериками

Возможный дубликат:
Перегрузка арифметического оператора для общего класса в С#

Вот код для генерического класса i, который был создан для добавления сложного числа для перегрузки оператора.

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);
    }
}

во время работы с этим я получил ошибку,

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

Может ли кто-нибудь предложить мне, как я могу использовать перегрузку оператора с помощью дженериков?

Ответ 1

Проблема заключается в том, что компилятор не может знать, можно ли применить оператор + к T. К сожалению, нет способа ограничить T числовым типом в С#.

Однако вы можете обходным путем использовать динамическое время выполнения:

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;
    }
}

Ответ 2

Если вы хотите обмануть, вы можете временно пометить их как тип dynamic и позволить среде выполнения определять, как это сделать. Пока тип T, который вы используете, определяет оператор +, он будет работать. Это означает, что он будет работать как для чисел, так и для строк, или любого другого типа (пользовательский или другой); не уверен, что это ваше намерение для Complex или нет. Кроме того, если нет оператора + для использования, исключение будет выдаваться во время выполнения; нет способа (что я знаю), чтобы выполнить проверку времени компиляции.

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);
    }
}

Использование примера со строками:

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!

Ответ 3

Вы не можете суммировать два типа общих объектов; в статической функции вы пытаетесь добавить два элемента типа T i._a и j._a., но T может быть любого типа

что вы пытаетесь сделать?

Ответ 4

Как упоминалось выше, вы можете ограничить T как IConvertible, а затем использовать тип decimal для выполнения требуемой математической функции следующим образом:

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));
    }
}