我在
Accessing a static property of a child in a parent method之后遇到了类似的问题.首选答案提示类的设计有缺陷,需要更多信息来讨论问题.
这是我想和你讨论的情况.
我想实现一些单位感知数据类型,如长度,质量,当前,…
应该有一个隐式转换来从给定的字符串创建实例.例如,“1.5米”应与“150厘米”相同,或“20英寸”应正确处理.
为了能够在不同的单位之间进行转换,我需要特定数量的转换常数.
我的想法是创建一个带有一些静态翻译方法的抽象基类.
那些应该使用特定于类的静态字典来完成它们的工作.
那么看看这个例子吧.
public class PhysicalQuantities { protected static Dictionary<string,double> myConvertableUnits; public static double getConversionFactorToSI(String baseUnit_in) { return myConvertableUnits[baseUnit_in]; } } public class Length : PhysicalQuantities { protected static Dictionary<string,double> myConvertableUnits = new Dictionary<string,double>() { { "in",0.0254 },{ "ft",0.3048 } }; } class Program { static void Main(string[] args) { Length.getConversionFactorToSI("in"); } }
我认为这给出了一个相当直观的用法,并使代码保持紧凑,可读性和可扩展性.但当然我遇到了引用post描述的相同问题.
现在我的问题是:如何通过设计避免这个问题?
解决方法
我认为这可以用泛型来解决,看起来仍然可读.根据Slaks的建议进行细化,以使注册适合静态构造函数,使其本身具有线程安全性.
所以如果我没有弄错的话:
>线程安全(所有工作在静态构造函数中的字典)
>语法仍然易于使用和可读SIConversion< Length> .GetFactor()(1个字符更多)
>需要在派生类上实现的代码非常样板寄存器(string,double); (实际上比你的字典定义短)
interface ISIConversionSubscriber { void Register(Action<string,double> regitration); } static class SIConversion<T> where T : ISIConversionSubscriber,new() { private static Dictionary<string,double>(); static SIConversion() { T subscriber = new T(); subscriber.Register(registrationAction); } public static double GetFactor(string baseUnit) { return myConvertableUnits[baseUnit]; } private static void registrationAction(string baseUnit,double value) { myConvertableUnits.Add(baseUnit,value); } } abstract class PhysicalQuantities : ISIConversionSubscriber { public abstract void Register(Action<string,double> register); } class Length : PhysicalQuantities { public override void Register(Action<string,double> register) { // for each derived type register the type specific values in this override register("in",1); } } class Program { static void Main(string[] args) { Console.WriteLine(SIConversion<Length>.GetFactor("in")); } }
输出:1
如果你想知道为什么我将PhysicalQuantities抽象化:避免将它与SIConversion< PhysicalQuantities> .GetFactor()一起使用,因为我们没有基类的转换.您可能不需要像这样的基类实例 – 它不是数量的完整表示,因此它可能只包含可重用的方法.
另一个建议是使用Enum作为baseUnit而不是字符串.既然每个人都在努力争取类型安全并且在魔术弦上大声吵嚷,那么它可能是一条很好的路径:))