我有这样的方法:
private static double ComputePercentage(ushort level, ushort capacity)
{
double percentage;
if(capacity == 1)
percentage = 1;
// do calculations...
return percentage;
}
是否可以使它成为类似“类型T”的泛型类型,它可以返回十进制或双精度,具体取决于预期的方法类型(或放入函数的类型?)
我试过这样的东西而且我无法让它工作,因为我不能将类似“1”的数字分配给泛型类型。我也尝试在ushort capacity)
之后使用“where T:”但我仍然无法理解。
private static T ComputePercentage<T>(ushort level, ushort capacity)
{
T percentage;
if(capacity == 1)
percentage = 1; // error here
// do calculations...
return percentage;
}
这甚至可能吗?我不确定,但我认为this post可能表明我想做的事情根本不可能。
修改
感谢所有回复的人,许多好的答案。正如Tomas指出的那样,这可能最好用两种不同的方法完成。正如TreDubZedd和TcKs所指出的,获得我想要的功能的最好方法是使用隐式转换,它可以隐式返回double或decimal。
答案 0 :(得分:5)
事实上,你不需要泛型,而是超载。但是,您需要通过IL支持的返回值类型进行重载,但C#不支持。
我为每个return的值类型优先选择两种方法:
static double ComputePercentageDouble (ushort level, ushort capacity)
static decimal ComputePercentageDecimal (ushort level, ushort capacity)
备选方案可以是具有隐式转换运算符的custome类型:
decimal decimalPercentage = ComputePercentage( 1, 2 );
double doublePercentage = ComputePercentage( 1, 2 );
static DoubleDecimal ComputePercentage( ushort level, ushort capacity ) {
DoubleDecimal percentage = default( DoubleDecimal );
if ( capacity == 1 )
percentage.Number = 1; // error here
// do calculations...
return percentage;
}
public struct DoubleDecimal {
public decimal Number;
public static implicit operator decimal( DoubleDecimal value ) {
return value.Number;
}
public static implicit operator double( DoubleDecimal value ) {
return (double)value.Number;
}
}
答案 1 :(得分:3)
答案 2 :(得分:3)
泛型可用于编写与任何类型一起使用的代码(可能实现某些接口,可以使用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>(...);
这是一个很好的技巧,它可能是你能得到的最好的(类型安全的)解决方法。但是,它有点复杂,因此声明两个单独的方法可能是一个更好的主意。
答案 3 :(得分:1)
它不漂亮,但请尝试:
percentage = (T)Convert.ChangeType(1, typeof(T));
至少适用于double
和decimal
。
答案 4 :(得分:0)
private static T ComputePercentage<T>(ushort level, ushort capacity)
{
if (typeof(T) == typeof(decimal))
{
decimal percentage = 1;
return (T) (object) percentage;
}
if (typeof(T) == typeof(double))
{
double percentage = 1;
return (T) (object) percentage;
}
throw new NotSupportedExcpetion();
}
答案 5 :(得分:0)
如果您使用的是C#4.0,则只需返回dynamic
。
答案 6 :(得分:0)
为什么不创建Percent类?
class Percent
{
public Percent(double value)
{
this.value = value;
}
public double AsDouble()
{
return value;
}
public decimal AsDecimal()
{
return (decimal)value;
}
readonly double value;
}
static Percent ComputePercentage(ushort level, ushort capacity)
{
double percentage = 0;
if (capacity == 1)
{
percentage = 1;
}
// calculations
return new Percent(percentage);
}