一、缘起 最近做项目,碰到一个很有意思的问题,虽然不是很难,但是在网络上看到资料却很少,我想这或许又是另一个被容易忽略的话题。 问题是这样的:项目中用到一个类,他有一个保存数据的属性Value,这个属性有个比较奇怪的地方就是,他的类型,是无法预先估计的,会随着软件的扩展而变化,也就是我们常说的动态类型。 二、分析问题 这个问题解决方法很容易就可以看出有2种: 1、使用object基类 使用这种方式能够解决问题,但是会引起装箱、拆箱等影响性能的低效操作,不可取; 2、使用泛型类 使用泛型类也是能够解决问题的,但是在所有使用该对象时指出具体的类型,而这个会让上层使用该类时因具体类不同而不好组织,也不可取; 三、解决问题 为了避免伤处麻烦,我采用了泛型类 + 泛型方法的模式来解决问题,简单的说,就是 1、把Value的类型抽象出来做成一个类,我们称他为DynamicValue,这个类含有DataType来存储Value的数据类型,并提供了泛型方法GetValue和SetValue来读写Value的值。 2、在从DynamicValue上,派生一个泛型类DynamicValue<T>,用来实际存储数据。 使用这个方法的好处就是,避免了使用object会产生的装箱、拆箱动作,封装了泛型类的具体类型变化,更加容易管理和使用了。 四、具体实现 看下面的代码: /// <summary>/// 动态数据类型/// </summary>public class DynamicValue { public string DataType { get; protected set; } /// <summary> /// 获取值之泛型方法 /// </summary> /// <typeparam name="T">值类型</typeparam> /// <returns> /// 值 /// </returns> public T GetValue<T>() { if (DataType == typeof(T).ToString()) { return ((DynamicValue<T>)this).Value; } return default(T); } /// <summary> /// 设置值之泛型方法 /// </summary> /// <typeparam name="T">值类型</typeparam> /// <param name="value">待复制参数</param> /// <returns> /// false:设置失败 /// true:设置成功 /// </returns> public bool SetValue<T>(T value) { if (DataType == typeof(T).ToString()) { ((DynamicValue<T>)this).Value = value; return true; } return false; } }/// <summary>/// 动态数据类型之泛型类/// </summary>/// <typeparam name="T"></typeparam>public class DynamicValue<T> : DynamicValue { /// <summary> /// 保存值 /// </summary> public T Value { get; set; } /// <summary> /// 构造函数 /// </summary> public DynamicValue() : this(default(T)) { } /// <summary> /// 构造函数 /// </summary> /// <param name="value"></param> public DynamicValue(T value) { Value = value; DataType = typeof(T).ToString(); } } 五、测试代码 class Program { static void Main(string[] args) { DynamicValue data = new DynamicValue<float>(12.3f); Console.WriteLine("类型正确,返回应有的值"); Console.WriteLine(data.GetValue<float>()); Console.WriteLine("类型不匹配,返回default(T),即:值类型为0,引用类型为null"); Console.WriteLine(data.GetValue<TestValue>()); data = new DynamicValue<TestValue>(new TestValue()); Console.WriteLine("类型不匹配,返回default(T),即:值类型为0,引用类型为null"); Console.WriteLine(data.GetValue<float>()); Console.WriteLine("类型正确,返回应有的值"); Console.WriteLine(data.GetValue<TestValue>()); Console.Write("Press any key to exit.."); Console.ReadKey(); } }class TestValue { public int Value { get; set; } public override string ToString() { return "Value = " + Value.ToString(); } } 六、测试结果 类型正确,返回应有的值 12.3 类型不匹配,返回default(T),即:值类型为0,引用类型为null 类型不匹配,返回default(T),即:值类型为0,引用类型为null 0 类型正确,返回应有的值 Value = 0 Press any key to exit.. 七、附录1、代码下载(这个就不提供了,反正上文已经都给出了,想动手调试的朋友,就自己复制粘贴下吧); 2、本系列其他文章:容易被忽略的细节(1):config文件的使用 相关文章: