Обобщения полезны для написания кода, который работает с любыми типами (возможно, реализует некоторый интерфейс, который можно указать с помощью where
). Однако, если вы хотите использовать их для реализации метода, который может возвращать два разных числовых типа, он будет немного ошибочным (он будет работать только в том случае, если double
и decimal
реализуют некоторый общий интерфейс).
Вам, вероятно, следует определить два разных метода (например, ComputePercentage
и ComputePercentagePrecise
или что-то в этом роде - поскольку вы не можете использовать перегрузку с использованием других параметров).
Может быть возможно обойти это ограничение, используя что-то вроде этого (но это, вероятно, слишком сложно для вас):
class INumericOps<T> {
public abstract T One { get; }
public abstract T Add(T a, T b);
// and other operations that you may need
}
// Implementations of numeric operations for decimal and double
class DecimalNumerics : INumericOps<decimal> { ... }
class DoubleNumerics : INumericOps<double> { ... }
Тогда вы бы написали метод, который принимает INumericOps<T>
в качестве параметра типа и использует его для выполнения всей математики внутри метода:
private static R ComputePercentage<T, R>(ushort level, ushort capacity)
where T : INumericOps<R>, where T : new() {
INumericOps<R> ops = new T(); // Get instance with numeric operations
T percentage;
if(capacity == 1)
percentage = ops.One;
// Calculations using ops.Add(.., ..) instead of + etc.
return percentage;
}
Тогда вы бы назвали это так:
decimal res = ComputePercentage<DecimalNumerics, decimal>(...);
Это хороший трюк и, вероятно, лучший (безопасный для типов) обходной путь, который вы можете получить. Однако это немного сложно, поэтому лучше объявить два отдельных метода.