C # Добавление двух общих значений - PullRequest
34 голосов
/ 14 ноября 2011

Может кто-нибудь объяснить, почему это не сработает?Я пытался иметь возможность добавить два значения независимо от числового типа.

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

При компиляции я получаю следующую ошибку:

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

Ответы [ 10 ]

59 голосов
/ 14 ноября 2011

Нет общего ограничения, позволяющего принудительно перегрузить оператор. Вы можете взглянуть на следующую библиотеку . В качестве альтернативы, если вы используете .NET 4.0, вы можете использовать ключевое слово dynamic:

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

Очевидно, что это не относится к безопасности времени компиляции, для чего и предназначены дженерики. Единственный способ применить безопасность времени компиляции - применить общие ограничения. А для вашего сценария нет доступных ограничений. Это всего лишь хитрость, чтобы обмануть компилятор. Если вызывающая сторона метода Add не передает типы, которые работают с оператором +, код вызовет исключение во время выполнения.

26 голосов
/ 18 июня 2013

Решения, приведенные здесь, работают хорошо, но я подумал, что добавлю еще одно, использующее выражения

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

Таким образом, вы создаете Func<T, T, T>, который выполняет сложение.Полное объяснение можно найти в этой статье .

10 голосов
/ 14 ноября 2011

Тип T не известен компилятору, поэтому он не может найти перегруженный оператор +, определенный где-либо ...

Лучшее, что вы можете сделать в настоящее время, это объявить ваш метод как таковой (поскольку все числовые типы являются конвертируемымиудвоить):

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

или если вы уверены, что будет определен подходящий оператор +:

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

Обновлено

иликомбинация двух:

public static T Add<T>(T in1, T in2)
{
    var d1 = Convert.ToDouble(in1);
    var d2 = Convert.ToDouble(in2);
    return (T)(dynamic)(d1 + d2);
}
6 голосов
/ 19 апреля 2013

Это проблема, с которой я столкнулся, когда мне нужен универсальный метод, который мог бы работать с произвольными списками чисел, например:

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

Я нашел решение использовать лямбда-выражение:

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

Который вы бы затем назвали

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

Очевидно, что в некоторых случаях вы можете просто использовать + внутри кода вместо лямбда-выражений, но если вам нужно для выполнения математических операций в общем виде, это была самая простая вещь, которую я мог придумать, это безопасная компиляция.

5 голосов
/ 30 октября 2015
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);
}
3 голосов
/ 22 июля 2017

Попробуйте этот код. Это общий код для добавления.

public static dynamic AddAllType(dynamic x, dynamic y)
{
    return  x + y;
}
2 голосов
/ 15 марта 2017

Это мешает разработчикам писать глючный код.Несколько вопросов, чтобы лучше объяснить вопрос:

1> Знает ли компилятор тип [Нет, потому что это универсальный тип].2> Может ли он принимать объекты в качестве параметра [Да, может, и из-за этого он не будет знать, что с ними делать -> ошибочный код]

Поскольку вы хотите, чтобы ваш код не содержал ошибок, C # не позволяет вам иметь '+' '-' и другие операторы.

Решение: вы можете использовать тип «dynamic», «var» и при необходимости возвращать их суммирование.

2 голосов
/ 19 июля 2013
        public class generic<T>
        {
            T result;
            public generic(T eval1, T eval2)
            {

                dynamic a = eval1;
                dynamic b = eval2;
                result = a + b;
                Console.WriteLine(result);
                Console.ReadLine();


            }

             static void Main(string[] args)
        {

             generic<int> genobj = new generic<int>(20,30);

        }
0 голосов
/ 23 июня 2017

Потому что никто не ответил, предоставив решение с использованием объекта.Поэтому я добавляю свое решение.В этом вы должны привести ваши общие значения к объекту.

Итак, это рабочий код:

public static T Add<T>(T number1, T number2)
{
    object a = number1;
    object b = number2;
    return (T)(object)((int)a * (int)b).ToString();
}
0 голосов
/ 14 ноября 2011

Как видно из сообщения об ошибке, оператор «+» не может быть применен. Это происходит потому, что компилятор ничего не знает о типе T. Он даже не знает, класс это или нет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...