我遇到的情况是我有一个业务对象,其中包含大约15种不同类型的属性。业务对象还必须实现具有以下方法的接口:
object GetFieldValue(string FieldName);
我可以看到实现此方法的两种方法:
使用switch语句:
switch ( FieldName )
{
case "Field1": return this.Field1;
case "Field2": return this.Field2;
// etc.
}
使用字典(SortedDictionary或HashTable?):
return this.AllFields[FieldName];
哪个更有效率?
已添加:忘了说。此方法用于在网格中显示项目。网格将为每个属性都有一列。通常会有超过1000个项目的网格。这就是我担心表现的原因。
已添加2:
这是一个想法:混合方法。创建一个静态字典,其中键是属性名称,值是数组中的索引。在应用程序启动时,字典仅填充一次。每个对象实例都有一个数组。所以,查找就像:
return this.ValueArray[StaticDictionary[FieldName]];
字典填充算法可以使用反射。然后将相应地实现属性本身:
public bool Field1
{
get
{
object o = this.ValueArray[StaticDictionary["Field1"]];
return o == null ? false : (bool)o;
}
set
{
this.ValueArray[StaticDictionary["Field1"]] = value;
}
}
任何人都可以看到有任何问题吗?
它还可以更进一步,ValueArray / StaticDictionary可以放在一个单独的泛型类型ValueCollection<T>
中,其中T
将指定反射的类型。 ValueCollection还将处理尚未设置任何值的情况。然后可以将属性简单地写为:
public bool Field1
{
get
{
return (bool)this.Values["Field1"];
}
set
{
this.Values["Field1"] = value;
}
}
最后,我开始怀疑,如果一个简单的switch语句可能不会更快更容易维护....
答案 0 :(得分:21)
switch: good efficiency, least maintainable
dictionary: good efficiency, better maintainability
reflection: least efficient, best maintainability
提示:忽略效率并仅担心可维护性,除非您实际测试了性能并发现它是一个问题。
我不是说反射是你唯一的选择,只是它允许你根据需要添加/删除和重命名属性,而不需要保持switch语句或字典同步。
答案 1 :(得分:7)
因为你正在使用字符串字典可能会更快。在使用字符串时,Switch基本上会转换为哈希表。但是如果你使用整数或类似的东西,它会被转换为跳转表并且会更快。
请参阅this answer并提问以了解更多详情
最好的办法是对其进行分析并确定
答案 2 :(得分:0)
如何获得每个属性的值可能对整体性能的影响小于渲染网格的方式。
我举个例子: 假设你有以下实现:
private string _latestFieldName = string.Empty;
private PropertyInfo _propertyInfo;
object GetFieldValue(string FieldName)
{
if(FieldName != _latestFieldName)
{
_propertyInfo = typeof(yourTypeName).GetProperty(FieldName);
}
return _propertyInfo.GetValue(this,null);
}
如果您的网格渲染使用反射一次渲染一行,则必须每次都获取propertyinfo。 如果你逐列渲染你只需要为每个属性获取一次propertyInfo,并且因为分支预测几乎每次你只错过if上的几个时钟周期。如果已经拥有PropertyInfo,则无需将调用结果转换为GetValue。在速度方面,使用反射非常接近使用属性的吸气剂。
我的观点是在您开始优化使用分析器之前。 (当然,如果你不能很好地改变网格,你也无法真正优化它)
答案 3 :(得分:0)
与字典相比,Switch实际上有两个好处: