Причина, по которой ваш код не компилируется, объясняется ошибкой компилятора.Содержащий тип является определением универсального типа, и универсальный тип , построенный из такого типа, не считается тем же типом.
У меня есть несколько вопросов:
- Почему тип
Rational
должен быть универсальным?Рациональное число определено как число, которое может быть выражено как отношение / дробь двух целых чисел (где знаменатель не 0
).Почему бы не сделать тип неуниверсальным и просто использовать int
повсюду?Или вы намереваетесь использовать этот тип для других целочисленных типов, таких как long
и BigInteger
?В этом случае рассмотрите возможность использования чего-либо, подобного предложению Алиостада, если вам нужен какой-то механизм совместного использования кода. - Почему вы хотите, чтобы произведение двух рациональных чисел было равно сумме их числителей над суммой ихзнаменатели?Это не имеет смысла для меня.
В любом случае, вы, похоже, хотите иметь возможность «в общем» добавить два экземпляра типа «добавляемый».К сожалению, в настоящее время нет никакого способа выразить ограничение «имеет подходящий оператор сложения» в C #.
Метод # 1: Одним из обходных путей для этого в C # 4 является использованиеdynamic
введите желаемую семантику "виртуального оператора".
public static Racional<T> operator *(Racional<T> a, Racional<T> b)
{
var nominatorSum = (dynamic)a.Nominator + b.Nominator;
var denominatorSum = (dynamic)a.Denominator + b.Denominator;
return new Racional<T>(nominatorSum, denominatorSum);
}
Оператор сгенерирует, если у типа нет подходящего оператора сложения.
Метод # 2: Другой (более эффективный) способиспользовать деревья выражений.
Сначала создайте и кэшируйте делегат, который может выполнить сложение, скомпилировав соответствующее выражение:
private readonly static Func<T, T, T> Adder;
static Racional()
{
var firstOperand = Expression.Parameter(typeof(T), "x");
var secondOperand = Expression.Parameter(typeof(T), "y");
var body = Expression.Add(firstOperand, secondOperand);
Adder = Expression.Lambda<Func<T, T, T>>
(body, firstOperand, secondOperand).Compile();
}
(Статический конструктор выдает, если тип неУ вас нет подходящего оператора сложения.)
Затем используйте его в операторе:
public static Racional<T> operator *(Racional<T> a, Racional<T> b)
{
var nominatorSum = Adder(a.Nominator, b.Nominator);
var denominatorSum = Adder(a.Denominator, b.Denominator);
return new Racional<T>(nominatorSum, denominatorSum);
}