Inline HashSet<> declaration vs static attribute, .Contains() performance - c#

In order to use the Contains method, what is better (is any difference), declare a static fieldwith the HashSet or declare it inline (new HashSet { SomeEnum.SomeValue1, SomeEnum.SomeValue2, ... }.Contains(SomeEnum.SomeValue1))
I ask that because in some cases I only going mto use the hashset once, and for me is better to have it on the code and not in some static attribute
Example inline (What I wanna use):
public void Validate(Type type) {
if(!new HashSet<Type> { Type.TYPE_1, Type.TYPE_2, Type.TYPE_3, Type.TYPE_4 }.Contains(type)) {
//do something
}
if(new HashSet<Type> { Type.TYPE_2, Type.TYPE_3, Type.TYPE_4, Type.TYPE_5 }.Contains(type)) {
//do something
}
}
Example static (What I prefer not to use):
private static HashSet<Type> _values1 = new HashSet<Type> { Type.TYPE_1, Type.TYPE_2, Type.TYPE_3, Type.TYPE_4 };
private static HashSet<Type> _values2 = new HashSet<Type> { Type.TYPE_2, Type.TYPE_3, Type.TYPE_4, Type.TYPE_5 };
public void Validate(Type type) {
if(!_values1.Contains(type)) {
//do something
}
if(_values2.Contains(type)) {
//do something
}
}
Example using logical expressions (What I don't want to use):
public void Validate(Type type) {
if(type != Type.TYPE_1 && type != Type.TYPE_2 && type != Type.TYPE_3 && type != Type.TYPE_4) {
//do something
}
if(type == Type.TYPE_2 || type == Type.TYPE_3 || type == Type.TYPE_4 || type == Type.TYPE_5) {
//do something
}
}

If you have not identified this as a bottleneck through performance testing, the the "right" way is just to use code that makes the most sense to people reading it. That's somewhat subjective, so there may not be a "right" way, but any approach that's not easy to understand will be the "wrong" way.
I would probably just use an inline-declared array, unless the list of values is reusable in other methods, or it's so long that it gets in the way of reading what the method is trying to do.
public void Validate(Type type) {
if(!new[] { Type.TYPE_1, Type.TYPE_2, Type.TYPE_3, Type.TYPE_4 }.Contains(type)) {
//do something
}
}
If you have identified this as a definite performance bottleneck (meaning you're probably doing this check millions of times per second, then you'll probably want to do performance testing on a few different approaches, because the correct answer depends on how many items are in the set you're trying to match against.
Besides the approaches you've suggested, here are a couple of other possibilities that will probably be faster (but again, you'd need to test them to make sure:
Flags Enum
It looks like you're using enum values. If that enum type has a small number of potential values, you could make it into a flags enum and then use bitwise logic to determine in a single CPU operation whether the given value matches any of the values you're looking for.
[Flags]
public enum Type
{
TYPE_1 = 1,
TYPE_2 = 1<<1,
TYPE_3 = 1<<2,
TYPE_4 = 1<<3,
TYPE_5 = 1<<4,
// etc...
}
Usage:
const Type toMatch = (Type.TYPE_1 | Type.TYPE_2 | Type.TYPE_3 | Type.TYPE_4);
if((type & toMatch) == 0)
{
// do something
}
Switch statement
The compiler is really good at figuring out what will be the fastest approach, so if you use a switch statement it can decide whether to compile that to a series of if/else checks, a HashSet-style approach, or a jump table, depending on the number and values of items you're trying to check.
switch(type)
{
case Type.TYPE_1:
case Type.TYPE_2:
case Type.TYPE_3:
case Type.TYPE_4:
break;
default:
// do something
break;
}

If no new items are going to be added then your static method is the correct way to do it
private static HashSet<Type> _values = new HashSet<Type> { Type.TYPE_1, Type.TYPE_2, Type.TYPE_3, Type.TYPE_4 };
public void Validate(Type type) {
if(!_values.Contains(type)) {
//do something
}
}
All collections in the System.Collections namespace are thread safe for read only operations so this is a perfectly acceptable way to do it.
If you did it your "preferred" way it would still work, however you would be re-creating the collection every time you call the function and that is a unnecessary overhead that would definitely hurt performance.

Keeping with the "infrequent" or "once" usage of the lookup in mind, as hinted by the post..
If the lookup is used only within the single method then I would use an inline approach, however I would us an array (and I actually do quite often). I may or may may not use an intermediate (local) variable, depending on if I it makes the code more clear or easy to adapt in the future.
I wouldn't use a static (or even instance) variable because:
The sequence is not shared in this case;
The of trivial amount of resources to create the object (especially for an array) is minimal;
The GC is really good with short-lived objects .. and, more importantly, there is no need to extend the lifetime
If I wanted to share this lookup across several methods, I would look into creating a getter that returned a new object (which covers #2 and #3 above while meeting the new requirement). With a local variable, individual methods would only create one new lookup per invocation.
I generally use an array because:
The syntax is marginally simpler (the type can be inferred and omitted);
The array (especially the construction) is more lightweight than a HashSet, yet provides the required lookup functionality;
Searching a small array is likely fast enough (as there is a very small n)
I would not use various long-hand forms if it makes the particular code harder to follow. The task is "contains", not some more complex conditional logic.
Unless there is an actual performance problem, do it a clean and simple way and move on with more interesting tasks.

Related

Is it possible to compare multiple values with one field? [duplicate]

Any easier way to write this if statement?
if (value==1 || value==2)
For example... in SQL you can say where value in (1,2) instead of where value=1 or value=2.
I'm looking for something that would work with any basic type... string, int, etc.
How about:
if (new[] {1, 2}.Contains(value))
It's a hack though :)
Or if you don't mind creating your own extension method, you can create the following:
public static bool In<T>(this T obj, params T[] args)
{
return args.Contains(obj);
}
And you can use it like this:
if (1.In(1, 2))
:)
A more complicated way :) that emulates SQL's 'IN':
public static class Ext {
public static bool In<T>(this T t,params T[] values){
foreach (T value in values) {
if (t.Equals(value)) {
return true;
}
}
return false;
}
}
if (value.In(1,2)) {
// ...
}
But go for the standard way, it's more readable.
EDIT: a better solution, according to #Kobi's suggestion:
public static class Ext {
public static bool In<T>(this T t,params T[] values){
return values.Contains(t);
}
}
C# 9 supports this directly:
if (value is 1 or 2)
however, in many cases: switch might be clearer (especially with more recent switch syntax enhancements). You can see this here, with the if (value is 1 or 2) getting compiled identically to if (value == 1 || value == 2).
Is this what you are looking for ?
if (new int[] { 1, 2, 3, 4, 5 }.Contains(value))
If you have a List, you can use .Contains(yourObject), if you're just looking for it existing (like a where). Otherwise look at Linq .Any() extension method.
Using Linq,
if(new int[] {1, 2}.Contains(value))
But I'd have to think that your original if is faster.
Alternatively, and this would give you more flexibility if testing for values other than 1 or 2 in future, is to use a switch statement
switch(value)
{
case 1:
case 2:
return true;
default:
return false
}
If you search a value in a fixed list of values many times in a long list, HashSet<T> should be used. If the list is very short (< ~20 items), List could have better performance, based on this test
HashSet vs. List performance
HashSet<int> nums = new HashSet<int> { 1, 2, 3, 4, 5 };
// ....
if (nums.Contains(value))
Generally, no.
Yes, there are cases where the list is in an Array or List, but that's not the general case.
An extensionmethod like this would do it...
public static bool In<T>(this T item, params T[] items)
{
return items.Contains(item);
}
Use it like this:
Console.WriteLine(1.In(1,2,3));
Console.WriteLine("a".In("a", "b"));
You can use the switch statement with pattern matching (another version of jules's answer):
if (value switch{1 or 3 => true,_ => false}){
// do something
}
Easier is subjective, but maybe the switch statement would be easier? You don't have to repeat the variable, so more values can fit on the line, and a line with many comparisons is more legible than the counterpart using the if statement.
In vb.net or C# I would expect that the fastest general approach to compare a variable against any reasonable number of separately-named objects (as opposed to e.g. all the things in a collection) will be to simply compare each object against the comparand much as you have done. It is certainly possible to create an instance of a collection and see if it contains the object, and doing so may be more expressive than comparing the object against all items individually, but unless one uses a construct which the compiler can explicitly recognize, such code will almost certainly be much slower than simply doing the individual comparisons. I wouldn't worry about speed if the code will by its nature run at most a few hundred times per second, but I'd be wary of the code being repurposed to something that's run much more often than originally intended.
An alternative approach, if a variable is something like an enumeration type, is to choose power-of-two enumeration values to permit the use of bitmasks. If the enumeration type has 32 or fewer valid values (e.g. starting Harry=1, Ron=2, Hermione=4, Ginny=8, Neville=16) one could store them in an integer and check for multiple bits at once in a single operation ((if ((thisOne & (Harry | Ron | Neville | Beatrix)) != 0) /* Do something */. This will allow for fast code, but is limited to enumerations with a small number of values.
A somewhat more powerful approach, but one which must be used with care, is to use some bits of the value to indicate attributes of something, while other bits identify the item. For example, bit 30 could indicate that a character is male, bit 29 could indicate friend-of-Harry, etc. while the lower bits distinguish between characters. This approach would allow for adding characters who may or may not be friend-of-Harry, without requiring the code that checks for friend-of-Harry to change. One caveat with doing this is that one must distinguish between enumeration constants that are used to SET an enumeration value, and those used to TEST it. For example, to set a variable to indicate Harry, one might want to set it to 0x60000001, but to see if a variable IS Harry, one should bit-test it with 0x00000001.
One more approach, which may be useful if the total number of possible values is moderate (e.g. 16-16,000 or so) is to have an array of flags associated with each value. One could then code something like "if (((characterAttributes[theCharacter] & chracterAttribute.Male) != 0)". This approach will work best when the number of characters is fairly small. If array is too large, cache misses may slow down the code to the point that testing against a small number of characters individually would be faster.
Using Extension Methods:
public static class ObjectExtension
{
public static bool In(this object obj, params object[] objects)
{
if (objects == null || obj == null)
return false;
object found = objects.FirstOrDefault(o => o.GetType().Equals(obj.GetType()) && o.Equals(obj));
return (found != null);
}
}
Now you can do this:
string role= "Admin";
if (role.In("Admin", "Director"))
{
...
}
public static bool EqualsAny<T>(IEquatable<T> value, params T[] possibleMatches) {
foreach (T t in possibleMatches) {
if (value.Equals(t))
return true;
}
return false;
}
public static bool EqualsAny<T>(IEquatable<T> value, IEnumerable<T> possibleMatches) {
foreach (T t in possibleMatches) {
if (value.Equals(t))
return true;
}
return false;
}
I had the same problem but solved it with a switch statement
switch(a value you are switching on)
{
case 1:
the code you want to happen;
case 2:
the code you want to happen;
default:
return a value
}

Looking for better understanding on the coding standards

I installed CodeCracker
This is my original method.
//Add
public bool AddItemToMenu(MenuMapper mapperObj)
{
using (fb_databaseContext entities = new fb_databaseContext())
{
try
{
FoodItem newItem = new FoodItem();
newItem.ItemCategoryID = mapperObj.ItemCategory;
newItem.ItemName = mapperObj.ItemName;
newItem.ItemNameInHindi = mapperObj.ItemNameinHindi;
entities.FoodItems.Add(newItem);
entities.SaveChanges();
return true;
}
catch (Exception ex)
{
//handle exception
return false;
}
}
}
This is the recommended method by CodeCracker.
public static bool AddItemToMenu(MenuMapper mapperObj)
{
using (fb_databaseContext entities = new fb_databaseContext())
{
try
{
var newItem = new FoodItem
{
ItemCategoryID = mapperObj.ItemCategory,
ItemName = mapperObj.ItemName,
ItemNameInHindi = mapperObj.ItemNameinHindi,
};
entities.FoodItems.Add(newItem);
entities.SaveChanges();
return true;
}
catch (Exception ex)
{
//handle exception
return false;
}
}
}
As far as I know Static methods occupy memory when the application intialize irrespective if they are called or not.
When I alrady know the return type then why should I use var keyword.
Why this way of Object intializer is better.
I am very curios to get these answer, as it can guide me in a long way.
Adding one more method:-
private string GeneratePaymentHash(OrderDetailMapper order)
{
var payuBizzString = string.Empty;
payuBizzString = "hello|" + order.OrderID + "|" + order.TotalAmount + "|FoodToken|" + order.CustomerName + "|myemail#gmail.com|||||||||||10000";
var sha1 = System.Security.Cryptography.SHA512Managed.Create();
var inputBytes = Encoding.ASCII.GetBytes(payuBizzString);
var hash = sha1.ComputeHash(inputBytes);
var sb = new StringBuilder();
for (var i = 0; i < hash.Length; i++)
{
sb.Append(hash[i].ToString("X2"));
}
return sb.ToString().ToLower();
}
As far as I know Static methods occupy memory when the application intialize irrespective if they are called or not.
All methods do that. You are probably confusing this with static fields, which occupy memory even when no instances of the class are created. Generally, if a method can be made static, it should be made static, except when it is an implementation of an interface.
When I already know the return type then why should I use var keyword.
To avoid specifying the type twice on the same line of code.
Why this way of Object intializer is better?
Because it groups the assignments visually, and reduces the clutter around them, making it easier to read.
Static methods don't occupy any more memory than instance methods. Additionally, your method should be static because it doesn't rely in any way on accessing itself (this) as an instance.
Using var is most likely for readability. var is always only 3 letters while many types are much longer and can force the name of the variable much further along the line.
The object initializer is, again, most likely for readability by not having the variable name prefix all the attributes. It also means all your assignments are done at once.
In most cases, this tool you're using seems to be about making code more readable and clean. There may be certain cases where changes will boost performance by hinting to the compiler about your intentions, but generally, this is about being able to understand the code at a glance.
Only concern yourself with performance if you're actually experiencing performance issues. If you are experiencing performance issues then use some profiling tools to measure your application performance and find out which parts of your code are running slowly.
As far as I know Static methods occupy memory when the application
initialize irrespective if they are called or not.
This is true for all kind of methods, so that's irrelevant.
When I already know the return type then why should I use var keyword.
var is a personal preference (which is a syntactic sugar). This analyzer might think since the return type is already known, there is no need to use type explicitly, so, I recommend to use var instead. Personaly, I use var as much as possible. For this issue, you might wanna read Use of var keyword in C#
Why this way of Object intializer is better.
I can't say object initializer is always better but object initialize supplies that either your newItem will be null or it's fully initialized since your;
var newItem = new FoodItem
{
ItemCategoryID = mapperObj.ItemCategory,
ItemName = mapperObj.ItemName,
ItemNameInHindi = mapperObj.ItemNameinHindi,
};
is actually equal to
var temp = new FoodItem();
newItem.ItemCategoryID = mapperObj.ItemCategory;
newItem.ItemName = mapperObj.ItemName;
newItem.ItemNameInHindi = mapperObj.ItemNameinHindi;
var newItem = temp;
so, this is not the same as your first one. There is a nice answer on Code Review about this subject. https://codereview.stackexchange.com/a/4330/6136 Also you might wanna check: http://community.bartdesmet.net/blogs/bart/archive/2007/11/22/c-3-0-object-initializers-revisited.aspx
A lot of these are personal preferences but most coding standards allow other programmers to read your code easier.
Changing the static method to an instance takes more advantage of OO concepts, it limits the amount of mixed state and also allows you to add interfaces so you can mock out the class for testing.
The var keyword is still statically typed but because we should concentrate on naming and giving our objects more meaningful so explicitly declaring the type becomes redundant.
As for the object initialisation this just groups everything that is required to setup the object. Just makes it a little easier to read.
As far as I know Static methods occupy memory when the application intialize irrespective if they are called or not.
Methods that are never called may or may not be optimized away, depending on the compiler, debug vs. release and such. Static vs. non-static does not matter.
A method that doesn't need a this reference can (and IMO should) be static.
When I already know the return type then why should I use var keyword
No reason. There's no difference; do whatever you prefer.
Why this way of Object intializer is better.
The object initializer syntax generates the same code for most practical purposes (see answer #SonerGönül for the details). Mostly it's a matter of preference -- personally I find the object initializer syntax easier to read and maintain.

Is there an accepted pattern to preserve variables' values during a function call which modifies those variables?

Within a class I have a property used by a method which I want to remain in the same state after a call to a second method (which might alter that state).
Example: for a property Value I could do something like this:
void MethodOne()
{
...
var tempValue = this.Value;
MethodTwo(); // might modify this.Value
this.Value = tempValue;
...
}
For a single property this isn't a big deal. If I have multiple properties it gets uglier.
I'm looking for a C# solution but would be interested to know if this kind of construct appears in any common language. The sort of syntax I'm after might look something like this:
void MethodOne()
{
...
preserving(this.Value)
{
MethodTwo(); // might modify this.Value
}
...
}
where the preserving keyword could potentially accept multiple properties/fields.
In my specific case it's a recursive method, so the code looks more like:
void MethodOne(object[] args)
{
...
// Do something which might modify this.Value
preserving(this.Value)
{
MethodOne(args);
}
...
}
Is there an accepted pattern / best practice to achieve this?
EDIT
The specific case for which I'm asking is something like this:
For the purposes of sorting lists I have a custom comparison class which implements IComparer. Its Compare method acts on objects which appear in collections (which may therefore be sorted). These collections might be nested, so sorting such a collection might result in the sort function, and therefore Compare(), being called recursively.
The actual comparison function is partially dynamic, which means that it could be set at runtime to something invalid (e.g. non-transitive or non-deterministic). I can't prevent this, so I want to set a limit on the number of comparisons (let's say n-squared, where n is the length of the list being sorted) to protect against cases where an invalid comparison function might result in the sorting algorithm going into an infinite loop.
The Compare method might be called from (e.g.) various LINQ methods such as OrderBy, possibly resulting in lazily evaluated sorts and possibly from code over which I have no control. However, I need to count the number of comparisons in each sort without any 'subsorts' of nested objects corrupting the count (but also counting comparisons in those subsorts).
My code looks something like this:
public int Compare(T x, T y)
{
// this.MaxComparisons is set from outside this code, since this method does not know the length of the list it is sorting.
if (++this.ComparisonCount > this.MaxComparisons)
{
// Error: too many comparisons
}
if (predicate)
{
// Preserve...
tempComparisonCount = this.ComparisonCount;
tempMaxComparisons = this.MaxComparisons;
// ...reset...
this.ComparisonCount = 0;
this.MaxComparisons = ... ; // set as required
var result = this.customComparer.Compare(x.Child, y.Child); // might involve further calls to the above method, which should be counted separately
// ...and restore
this.ComparisonCount = tempComparisonCount;
this.MaxComparisons = tempMaxComparisons;
return result;
}
else
{
return otherComparer.Compare(x, y);
}
}
I hope this makes it clearer why I have asked the question.
private static void Preserving<T>(ref T value, Action act)
{
T old = value;
act();
value = old;
}
then you can do:
Preserving(ref this.Value, MethodTwo);
If you have multiple variables you want to save and restore, you should probably create a Context class containing the state you want to save and then push/pop them from a stack.

Reducing Duplicated Code

I have some code that works on the color structure like this
public void ChangeColor()
{
thisColor.R = thisColor.R + 5;
}
Now I need to make a method that changes a different variable depending on what it is passed. Here is what the code looks like now.
public void ChangeColor(int RGBValue)
{
switch(RGBValue)
{
case 1:
thisColor.R = thisColor.R + 5;
break;
case 2:
thiscolor.B = thisColor.B + 5;
break;
}
}
Now, this is something I would normally never question, I'd just throw a #region statement around it and call it a day, but this is just an example of what I have, the actual function is quite long.
I want it to look like this:
public void ChangeColor(int RGBValue)
{
thiscolor.RGBValue = thiscolor.RGBValue;
}
So essentially the value would refer to the variable being used. Is there a name for this? Is this what Reflection is for? Or something like that... Is there a way to do this?
I'm not 100% sure if this is what you want. But with the given example, it sounds like this might be what you're after.
you might be able to use the ref keyword:
public void ChangeColor(ref int color)
{
color += 5;
}
void SomeMethod()
{
ChangeColor(ref thisColor.R); //Change the red value
ChangeColor(ref thisColor.B); //Change the blue value
}
This is definitely not what reflection is for. In fact, there seem to be a number of issues here. Let's review here - you want to change the following method:
public void ChangeColor(int RGBValue)
{
switch(...)
{
case ...
case ...
case ...
}
}
Into something like this:
public void ChangeColor(int RGBValue)
{
thisColor.{something-from-RGBValue} += 5;
}
The problems with this are:
The name of the method, ChangeColor, does not precisely describe what the method actually does. Perhaps this is an artifact of anonymization, but nevertheless it's a terrible name for the method.
The parameter, RGBValue, does not accurately describe what the argument is or does. The name RGBValue and the type int makes it sound like an actual RGB color value, i.e. 0x33ccff for a light blue. Instead it chooses which of R, G, or B will be set.
There are only 3 valid values for the parameter, and yet the range of possible values is completely unrestricted. This is a recipe for bugs. Worse, individual values are used as magic numbers inside the method.
But perhaps most important of all, the "clean/quick method" you are asking for is precisely the abstraction that this method purports to provide! You're writing a method that intensifies the hue, and in order to keep the method short, you're asking for... a method to intensify the hue. It doesn't make sense!
I can only assume that you want to do this because you have many different things you might want to do to a Color, for example:
public void Brighten(...) { ... }
public void Darken(...) { ... }
public void Desaturate(...) { ... }
public void Maximize(...) { ... }
And so on and so forth. And you're trying to avoid writing switch statements for all.
Fine, but don't eliminate the switch entirely; it is by far the most efficient and readable way to write this code! What's more important is to distill it down to one switch instead of many, and fix the other problems mentioned above. First, let's start with a reasonable parameter type instead of an int - create an enumeration:
public enum PrimaryColor { Red, Green, Blue };
Now, start from the idea that there may be many actions we want to perform on one of the primary colors of a composite color, so write the generic method:
protected void AdjustPrimaryColor(PrimaryColor pc, Func<byte, byte> adjustFunc)
{
switch (pc)
{
case PrimaryColor.Red:
internalColor.R = adjustFunc(internalColor.R);
case PrimaryColor.Green:
internalColor.G = adjustFunc(internalColor.G);
default:
Debug.Assert(pc == PrimaryColor.Blue,
"Unexpected PrimaryColor value in AdjustPrimaryColor.");
internalColor.B = adjustFunc(internalColor.B);
}
}
This method is short, easy to read, and will likely never have to change. It is a good, clean method. Now we can write the individual action methods quite easily:
public void Brighten(PrimaryColor pc)
{
AdjustPrimaryColor(pc, v => v + 5);
}
public void Darken(PrimaryColor pc)
{
AdjustPrimaryColor(pc, v => v + 5);
}
public void Desaturate(PrimaryColor pc)
{
AdjustPrimaryColor(pc, v => 0);
}
public void Maximize(PrimaryColor pc)
{
AdjustPrimaryColor(pc, v => 255);
}
The (significant) advantages to this are:
The enumeration type prevents callers from screwing up and passing in an invalid parameter value.
The general Adjust method is easy to read and therefore easy to debug and easy to maintain. It's also going to perform better than any reflection-based or dictionary-based approach - not that performance is likely a concern here, but I'm mainly saying this to note that it certainly isn't going to be worse.
You don't have to write repeated switch statements. Each individual modifier method is exactly one line.
Eventually, somewhere, you're actually going to have to write some code, and I would much rather that code be an extremely simple switch statement than a mess of reflection, delegates, dictionaries, etc. The key is to generalize this work as much as possible; once you've done that and created that abstraction, then you can start writing one-liner methods to do the "real" work.
It's a bit awkward, but you can pass a property 'by ref' like this:
int ThisColor { get; set; }
public void ChangeColor(Func<int> getter, Action<int> setter)
{
setter(getter() + 5);
}
public void SomeMethod()
{
ChangeColor(() => ThisColor, (color) => ThisColor = color);
}
This is less expensive than reflection and it's compile-time checked (with reflection, you'd have to pass a string to a GetProperty call and the string name could potentially diverge from the property name in later refactoring.)
I would tend to use a dictionary rather than what i suspect could end up being a large switch statement so if you created a
Dictionary<int,Func<int,int>> map = new Dictionary<int, Func<int, int>>();
Each item in your dictionary could take then input and return the new value
so you your method you would be able to call
public int ChangeColor(int rgbValue)
{
return map[rgbValue](rgbValue);
}
which will execute the delegate specific for the Rgb value you insert, to assign a delegate you simply add a new entry to the map
map.Add(5,x => x+5);
If I understand you correctly, you'd like to write a method that takes some symbol (or property name) and modifies the property of the structure using defined by this symbol. This isn't easily possible in C# (you could of course use reflection, but...).
You could do similar thing using Dictionary containing delegates for reading and writing the value of the property. However, that will still be a bit lengthy, because you'll need to initialize the dictionary. Anyway, the code might look like this:
var props = new Dictionary<string, Tuple<Func<Color, int>, Action<Color, int>>>
{ "R", Tuple.Create(c => c.R, (c, r) => c.R = r),
"G", Tuple.Create(c => c.G, (c, g) => c.G = g),
"B", Tuple.Create(c => c.B, (c, b) => c.B = b) };
This creates a dictionary that contains string (name of the property) as the key and a tuple with getter delegate and setter delegate for each of the property. Now your ChangeColor method could look like this:
public void ChangeColor(string propName) {
var getSet = props[propName];
getSet.Item2(thisColor, getSet.Item1(thisColor) + 5);
}
The code would be more readable if you used your own type with Get property and Set property instead of Tuple with properties named Item1 and Item2. This solution may be useful in some scenarios, but you still need to explicitly list all the properties when initializing the dictionary.
This might be what your looking for, you may want to add some error handling though.
It will work with any kind of property with public get; and set; methods.
And if you want to there is ways to reduce use of "magic-strings".
public static void ChangeProperty<T>(this object obj, string propertyName, Func<T,T> func)
{
var pi = obj.GetType().GetProperty(propertyName);
pi.SetValue(obj, func((T)pi.GetValue(obj, null)), null);
}
public void Change()
{
thisColor.ChangeProperty<int>("R", (x) => x + 5);
}
Well, it's kind of hard to tell what's really going on since you've given a very simplified example.
But, what I'm really reading is that you want to have a method that will perform one of a number of possible modifications to local state based upon one of the parameters of the method.
Now, is the operation the same, except for what it's being done to?
Ultimately, you have to have some code that understandds that maps an input to a desired operation. How much that can be generalized depends upon how similar the actions are (if it's always 'add 5 to a property' you have more generalization options...).
Some options you have are:
Write a class which encapsulates the Color struct.
Use a lookup table of Actions, as suggested by Kev Hunter.
Write a switch statement.
Pass in a parameter which contains a virtual method which can be executed on the internal data (or just pass in an Action<> directly) - avoiding the lookup
And... that's about it, really. Which one of these makes the most sense probably depends more on your actual use case (which we don't really have a lot of info on) than anything else.

What's the best alternative to an out of control switch statement?

I have inherited a project that has some huge switch statement blocks, with some containing up to 20 cases. What is a good way to rewrite these?
Why would you want to rewrite them in a different structure? If you really have 20 cases that have to be handled individually, a switch/case is the way to go. A big chain of if/then logic would be horrible to maintain.
Polymorphism is another option if you are using an object-oriented language. Each subclass would implement it's own functionality in the method.
Polymorphism. But it may not be a trivial refactoring.
Some examples and refs:
Refactoring (Googe books)
Switch Statement code smell and Polymorphism
Refactoring switch-statements
As others have pointed out, it depends on the switch statement. However, in the past I have refactored switch statements by proceeding in the following way. Suppose we have a switch statement like this, with a lot of repeating code
switch(x){
case 1:
makeitso("foo");
globalLog += "foo";
case 2:
makeitso("bar");
globalLog += "bar";
case 3:
makeitso("baz");
globalLog += "baz";
...
default:
throw("input error");
}
the first thing to do is to recognize the parts that are common (in the real world, this will probably be a little more substantial)
makeitso([some string]);
globalLog += [some string];
and turn that into a function
function transformInput(somestring) {
makeitso(somestring);
globalLog += somestring;
}
then for the parts that change in each case, use a hash or an array;
var transformvalues = ["foo", "bar", "baz"];
from here we can do this:
var tvals = ["foo", "bar", "baz" ... ];
function transformInput(somestring) {
makeitso(somestring);
globalLog += somestring;
}
var tval = tvals[x];
if(tval!==undefined) {
transformInput(tval);
} else {
throw ("invalid input");
}
And with tvals factored out of the switch statement, it could even be provided externally to expand the number of cases you can handle. Or you could build it dynamically. In the real world, the switch statement will often have special cases, however. I leave that as an excercise for the reader.
Three suggestions (echoing some already given):
Maybe a switch isn't as bad as you think. It can be ugly if the case blocks are large. Shorten them by extracting the logic into methods.
In an OO language, polymorphism might be the answer, as many have pointed out.
In a functional language, like Javascript, write a function that returns the function you need to run for whatever input. That might use a switch statement itself, or it might use a lookup table.
You could always use a lookup table.
There's nothing wrong with having 20 cases in a switch statement. You can tidy the code by refactoring and, at the very least, move the case processing into methods/functions.
Depending on what the switch statement is evaluating, you may want to refactor it using the Strategy Pattern. Take a look at this post for an example of replacing a switch on enum values with separate classes to handle each function.
It also may be that using the switch with 20 cases may actually be the best course of action for it. As long as it's readable and each result clearly conveys what the action is there's no need to really refactor it.
In general, I think you should refactor only when you need to, such as when you want to add more features, but the current design isn't up for the task. You should then refactor without adding the new functionality, and only then add the new feature.
In other circumstances, don't bother with refactoring. Do it when you need to, otherwise there are probably more important things to do.
If you really really need to, then the Visitor Design Pattern is a common switch-case replacement, though you should note it does have drawbacks. (i.e., check out www.objectmentor.com/resources/articles/acv.pdf)
It depends what the switch statement is doing.
If it's matching characters or strings, say in a parser, and you don't have the same set of patterns repeated everywhere in the code, then a switch statement might be ok.
If it's matching (say) an integer against a list of allowed values, you can create a base class and a set of derived classes for each value. Then, whatever generates the integer data in the first place can create an instance of the derived class with all of the switch statement "answers" instead.
A third option is to create a data structure that maps patterns to actions (i.e., functions or objects with virtual methods). You can look up the switch value in this data strucutre, and execute the appropriate action.
if it's working without major bugs (by not major I mean they don't make you pull your hair out) why bother refactor it? Don't refactor everything.
If you want, you can change it to polymorphism, but this will be a shotgun surgery, you'll probably have to refactor a whole lot more than just this switch block.
Visit https://github.com/Pedram-Ahmadpour/Switch-Case
Client side
Create an instance of your Condition, then pass a condition to Condition object by Switch() function.
int sense = 2;
ConditionSense conditionSense = new ConditionSense();
conditionSense.Switch(sense);
Server side
Create a condition action. This interface defines how to execute a Condition.
public interface IAction
{
void Do();
}
Create list of cases you want. These classes must implement condition action and ICase; Keep them light.
public class CaseCry : IAction, ICase<int?>
{
public int? Key { get { return 2; } }
public void Do()
{
Sense.Cry cry = new Sense.Cry();
cry.Act();
}
}
ICase just holds a Key that it is used by Switch() function to navigate the cases.
public interface ICase<TCase>
{
TCase Key { get; }
}
Create a Condition class that it Inherites SwitchCase generic abstract class.
Add all cases witch you want to Cases property.
Define a Switch() function and navigate Cases property to find matches cases, then execute them as a condition action.
public class ConditionSense : SwitchCase<int?>
{
public ConditionSense()
{
Cases = new List<ICase<int?>>
{
new CaseSmile(),
new CaseCry()
};
DefaultCases = new List<ICase<int?>> {
new CaseNoSense()
};
}
public void Switch(int? key)
{
IEnumerable<IAction> matches = Cases.Where(p => p.Key.Equals(key))
.Select(p => p as IAction);
if (matches.Count() > 0)
foreach (IAction match in matches)
match.Do();
else
foreach (IAction defaultCase in DefaultCases)
defaultCase.Do();
}
}
Smile, Cry..., can be huge, don't worry about size of them; condition action and ICase keep them lazy load.
public class Sense
{
public class Smile
{
public void Act()
{
Console.WriteLine("I'm smiling :-)");
}
}
public class Cry
{
public void Act()
{
Console.WriteLine("I'm crying :-(");
}
}
public class NoSense
{
public void Act()
{
Console.WriteLine("I've no sense :-|");
}
}
}

Categories

Resources