Универсальные методы: возвращение двойного или двойного класса
В настоящее время я реализую простую версию алгоритмического дифференцирования с перегрузкой операторов в C#. Я пытаюсь выяснить, как спроектировать общие математические функции, которые работают с обычными типами double, и мой собственный класс "ADouble", который работает как тип double, но перегружает арифметические операторы, такие как +,*,- и так далее.
Например, я хотел бы создать такую функцию, как
Public T MathFunction<T>(T x) where T : "is either double or Adouble"
{
if (x > 0)
return new T(1.0)
else
// something
}
это работает как для пар, так и для двойников. В этом случае мне необходимо "обновить" определенное значение (здесь 1.0). В других случаях я мог бы сделать что-то вроде
Public T MathFunction<T>(T x) where T : "is either double or Adouble"
{
T temporaryVar = 2*x;
// .. More calculations
return "some T";
}
Я реализовал необходимые интерфейсы, чтобы сделать сравнение, как указано выше, но я не могу заставить остальные работать.
Я могу создать экземпляр моего класса Double с помощью
Adouble myADouble = new ADouble(12.3);
но double не имеет конструктора, который работает таким образом, очевидно. Я пробовал разные вещи. Прежде всего, я подумал о чем-то вроде
if (typeof(T) == typeof(ADouble)
return new ADouble(1.0)
но это не работает, так как функция не может явно привести ADouble к T (что я понимаю).
Кто-нибудь есть предложение о том, как я мог бы реализовать общие функции расчета, который работает с моим классом ADouble и удваивается? Или это единственный вариант сделать несколько методов с разными сигнатурами? Различные предложения по проектам также высоко ценится.
1 ответ
Или это единственный вариант сделать несколько методов с разными сигнатурами?
Называется "метод перегрузки".
Да. Это правильный способ выражения вашего ограничения типа "А" или "Тип В", тем более что даже если вы можете успешно выразить это как общее ограничение, вы все равно будете вынуждены вызывать соответствующий конструктор.
В обобщениях C# нет механизма, с помощью которого return new T(1.0);
может быть сделано для успешной компиляции. Для этого потребуется некоторый синтаксис, который дополнительно ограничивает типы теми, у которых есть конструктор с единственным параметром типа double
и нет такой функции в C#.
это не работает, так как функция не может явно привести ADouble к T
На самом деле, это то, что он не может быть использован неявно. Но достаточно близко.:)
Это будет следующим препятствием, которое вам придется преодолеть. Как ни странно, это самое простое. Проблема в том, что, когда вы написали выражение, компилятор знает достаточно о том, что происходит, и не может гарантировать, что приведение будет успешным. Но если вы приведете значение к object
во-первых, вы можете затем привести его к T
без жалоб компилятора.
Не то чтобы я предлагал это сделать, заметьте. Настоящая проблема здесь в том, что вы пытаетесь использовать универсальный синтаксис для чего-то, что действительно не является универсальным. Общий код предназначен для использования любого типа или, по крайней мере, широко ограниченного типа. Если вы имеете в виду конкретные типы, и особенно если реализация отличается для каждого конкретного типа, то вам не следует использовать универсальные шаблоны.
В этой ситуации перегрузка метода гораздо более уместна.
В сторону: при условии вашего ADouble
тип буквально эквивалентен double
и вы можете реализовать преобразование без потери данных, вам следует подумать о написании неявного преобразования, чтобы сделать типы взаимозаменяемыми. Это будет выглядеть примерно так:
public static implicit operator ADouble(double value)
{
return new ADouble(value);
}
Тогда вы можете инициализировать ADouble
значения с простыми присваиваниями, например:
ADouble adouble = 1.0;