【发布时间】:2015-05-02 03:26:42
【问题描述】:
我正在尝试创建一个度量单位类库。
到目前为止我所拥有的是:
public abstract class UnitBase
{
protected double unitValue;
protected readonly double toSiFactor;
//more stuff goes here
}
//Meters, feet, miles etc will derive from this
public class LengthUnit : UnitBase
{
//various methods and operator overloading
//Among others there is To<> for conversions, not really needed
//to understand the problem but relevant.
public L To<L>() where L : LengthUnit, new()
{
L converted = new L();
converted.FromSi(ToSi()); //ToSi() and FromSi() are in UnitBase, omitted for brevity
return converted;
}
}
//Seconds Hours etc will derive from this
public class TimeUnit : UnitBase
{
//Add() Subtract methods and various operator overloading
}
到目前为止一切顺利。但现在我想创建复杂的单位类型,例如速度。所以这里是:
public class SpeedUnit<S, T> : UnitBase
where S : LengthUnit, new()
where T : TimeUnit, new()
{
//=======================
//HERE IS THE AWKWARDNESS
//=======================
public U To<U, S1, T1>()
where U : SpeedUnit<S1, T1>, new()
where S1 : LengthUnit, new()
where T1 : TimeUnit, new()
{
U converted = new U();
converted.FromSi(ToSi());
return converted;
}
}
public class Knots : SpeedUnit<NauticalMiles, Hours>
{
//omitted code
}
public class FeetPerMinute : SpeedUnit<Feet, Minutes>
{
//omitted code
}
所以这是我的问题:假设您有 Knots,并且您想将它们转换为 FeetPerMinute。理想的情况是:
Knots kts = new Knots(20);
FeetPerMinute = kts.To<FeetPerMinute>();
相反,我必须这样做:
FeetPerMinute = kts.To<FeetPerMinute, Feet, Minutes>();
这有点尴尬,而且当涉及到更复杂的类型(例如力)时,情况可能会变得更糟。 To() 将类似于:
Newtons n = someForce.To<Newtons, Kilograms, Meters, Seconds>()
如果你错误地使用了加速类型,甚至更糟:
Newtons n = someForce.To<Newtons, Kilograms, Acceleration<Meters, Seconds>, Meters, Seconds>()
不是很方便,特别是如果您考虑简单的话。 所以我的问题是:
- 有什么方法可以使这项工作? (除了从
SpeedUnit中删除通用参数) - 为什么编译器臭名昭著的类型推断不能发现
Meters和Seconds已经存在于MetersPerSecond中?
【问题讨论】:
-
static From<U, S1, T1>(U value)怎么样? -
@OndrejTucny 啊不,我担心这行不通:
From的返回类型是什么?U?还是其他类型的U1?别忘了我想从Knots(U) 转换为FeetPerMinute(U1)。
标签: c# generics units-of-measurement