【发布时间】:2010-09-25 19:39:18
【问题描述】:
受Units of Measure in F# 的启发,尽管断言 (here) 无法在 C# 中实现,但前几天我有了一个想法,我一直在玩弄。
namespace UnitsOfMeasure
{
public interface IUnit { }
public static class Length
{
public interface ILength : IUnit { }
public class m : ILength { }
public class mm : ILength { }
public class ft : ILength { }
}
public class Mass
{
public interface IMass : IUnit { }
public class kg : IMass { }
public class g : IMass { }
public class lb : IMass { }
}
public class UnitDouble<T> where T : IUnit
{
public readonly double Value;
public UnitDouble(double value)
{
Value = value;
}
public static UnitDouble<T> operator +(UnitDouble<T> first, UnitDouble<T> second)
{
return new UnitDouble<T>(first.Value + second.Value);
}
//TODO: minus operator/equality
}
}
示例用法:
var a = new UnitDouble<Length.m>(3.1);
var b = new UnitDouble<Length.m>(4.9);
var d = new UnitDouble<Mass.kg>(3.4);
Console.WriteLine((a + b).Value);
//Console.WriteLine((a + c).Value); <-- Compiler says no
下一步是尝试实现转换(sn-p):
public interface IUnit { double toBase { get; } }
public static class Length
{
public interface ILength : IUnit { }
public class m : ILength { public double toBase { get { return 1.0;} } }
public class mm : ILength { public double toBase { get { return 1000.0; } } }
public class ft : ILength { public double toBase { get { return 0.3048; } } }
public static UnitDouble<R> Convert<T, R>(UnitDouble<T> input) where T : ILength, new() where R : ILength, new()
{
double mult = (new T() as IUnit).toBase;
double div = (new R() as IUnit).toBase;
return new UnitDouble<R>(input.Value * mult / div);
}
}
(我本来希望避免使用静态实例化对象,但我们都知道你can't declare a static method in an interface) 然后你可以这样做:
var e = Length.Convert<Length.mm, Length.m>(c);
var f = Length.Convert<Length.mm, Mass.kg>(d); <-- but not this
显然,与 F# 度量单位相比,这有一个巨大的漏洞(我会让你算出来的)。
哦,问题是:您对此有何看法?值得使用吗?其他人已经做得更好了吗?
更新对于对此主题领域感兴趣的人,here 是 1997 年的一篇论文的链接,该论文讨论了一种不同的解决方案(不是专门针对 C#)
【问题讨论】:
-
看看 Frink 计算器和 Frink 编程语言。
-
我想知道是否有人在 C# 中使用类属性值的属性来处理单元。
-
Frink 是这类问题的炸弹。
-
我可能在这里遗漏了一些明显的东西,但是您为什么想要/需要另一个(即 F# 以外的)基于 CLR 的度量单位实现?还是只是为了“这样做”?
-
@pblasucci,只是为了它。 (只是为了挑剔,F# 实现不是基于 CLR,这一切都发生在编译器中,运行时什么都看不到)...
标签: c# f# units-of-measurement