Reputation: 106980
I've got a situation where I have a business object with about 15 properties of different types. The business object also has to implement an interface which has the following method:
object GetFieldValue(string FieldName);
I can see 2 ways of implementing this method:
Use a switch statement:
switch ( FieldName )
{
case "Field1": return this.Field1;
case "Field2": return this.Field2;
// etc.
}
Use a dictionary (SortedDictionary or HashTable?):
return this.AllFields[FieldName];
Which would be more efficient?
Added: Forgot to say. This method is for displaying the item in a grid. The grid will have a column for each of these properties. There will routinely be grids with a bit over 1000 items in them. That's why I'm concerned about performance.
Added 2:
Here's an idea: a hybrid approach. Make a static dictionary with keys being property names and values being indices in array. The dictionary is filled only once, at the startup of the application. Every object instance has an array. So, the lookup would be like:
return this.ValueArray[StaticDictionary[FieldName]];
The dictionary filling algorithm can use reflection. The properties itself will then be implemented accordingly:
public bool Field1
{
get
{
object o = this.ValueArray[StaticDictionary["Field1"]];
return o == null ? false : (bool)o;
}
set
{
this.ValueArray[StaticDictionary["Field1"]] = value;
}
}
Can anyone see any problems with this?
It can also be taken one step further and the ValueArray/StaticDictionary can be placed in a separate generic type ValueCollection<T>
, where T
would specify the type for reflection. ValueCollection will also handle the case when no value has been set yet. Properties could then be written simply as:
public bool Field1
{
get
{
return (bool)this.Values["Field1"];
}
set
{
this.Values["Field1"] = value;
}
}
And in the end, I'm starting to wonder again, if a simple switch statement might not be both faster and easier to maintain....
Upvotes: 11
Views: 6757
Reputation: 916
Switch actually has 2 benefits comparing to dictionary:
Upvotes: 0
Reputation: 62145
switch: good efficiency, least maintainable
dictionary: good efficiency, better maintainability
reflection: least efficient, best maintainability
Hint: ignore efficiency and worry about maintainability only, unless you've actually tested performance and found it be be an issue.
I'm not saying reflection is your only choice, just that it would allow you to add/remove and rename properties as needed, and not need to keep the switch statement or dictionary in sync.
Upvotes: 22
Reputation: 21752
How you get the value of each property will probably have a lesser impact on the overall performance than how you render your grid.
Let me give you an example: let's say you have the following implementation:
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);
}
If your grid rendering is rendering a row at a time using reflection it will have to get the propertyinfo every single time. wheras if you render column by column you'd only have to get the propertyInfo once for each property and since the branch prediction will be right almost every time you'd only miss a very few clock cycles on the if. When you have the PropertyInfo already and you don't need to cast the result of the call to GetValue. using reflection comes VERY close to using the getter of a property when it comes to speed.
My point is before you start to optimize use a profiler. (Of course if you can't change the grid well you can't really optimize it either)
Upvotes: 0
Reputation: 46193
Because you are using strings Dictionary will probably be faster. Switch will essentially get translated to a hashtable when using strings. But if you are using ints or similar it gets translated to a jump table and will be faster.
see this answer and question for more details
Best bet is to profile it and find for sure
Upvotes: 8