What is the best universal approach (speed and handling) for managing constant data that is dependant on one or several conditional variables (int, float, string, ...)?
Basic examples:
Car CreateCar(int brand)
{
//...
float colourValue = GetRandomFloat(0F, 1F);
car.Coulor = GetCarCoulor(brand, colourValue);
//...
}
//-------------
//Example for data functions:
//-------------
string GetCarCoulor(int brand, float colourValue)
{
if (brand == 0)
{
if (colourValue < 0.3)
return "red";
else if (colourValue < 0.7)
return "green";
else
return "blue";
}
else if (brand == 1)
{
if (colourValue < 0.2)
return "red";
else
return "blue";
}
//...
return "default";
}
float GetCarSpeed(int brand, int carModel, int gear, bool returnMin)
{
if (brand == 0)
{
if (carModel == 0)
{
if (gear == 1)
{
if (returnMin)
return 1F;
else
return 15F;
}
else if (gear == 2)
{
if (returnMin)
return 15F;
else
return 40F;
}
}
//...
}
else if (brand == 1)
{
//...
}
//...
return 0F;
}
Functions with if-else constructs are obviously the most basic form that work for most data but doesn't necessarily look/handle and perform very well with bigger data sets. Otherwise there are Dictionary<T1,T2>
and switch
constructs that come to mind, but these don't work that well with multiple or some types of input variables.
So are there any other kinds of constructs/approaches to look up constant data or some kind of best practice rules for that?
I also read of using XML files for data storage. Is this generally advisable for these kind of data, or is it slower or adds too much complexity? Advantages/disadvantages?
EDIT: Extended example to show what kind of data functions I had in mind.
As an alternative approach, you could have a dictionary of "rules" as long as your input types stay the same.
I actually wouldn't recommend this (see the note below), but it's a possibility.
void Main()
{
List<RuleResultPair> rules = new List<RuleResultPair>();
rules.Add(new RuleResultPair
{
Rule = (input) => input.A == 0 && input.B < 0.3,
Result = "output1.1"
});
rules.Add(new RuleResultPair
{
Rule = (input) => input.A == 0 && input.B < 0.7,
Result = "output1.2"
});
var test1Point1 = new Input
{
A = 0,
B = 0.2F
};
var test1Point2 = new Input
{
A = 0,
B = 0.7F
};
rules.First(w => w.Rule(test1Point1)).Result.Dump(); //outputs output1.1
rules.First(w => w.Rule(test1Point2)).Result.Dump(); //outputs output1.2
}
// Define other methods and classes here
public struct Input
{
public int A;
public float B;
}
public class RuleResultPair
{
public Predicate<Input> Rule;
public string Result;
}
http://share.linqpad.net/pqouhc.linq
I'm sure this code can be improved greatly, but I want to keep it relatively simple for the purpose of example.
It looks like this could lead to a maintenance problem. Often blocks of switch statements or if statements are a bit of a code smell.
It looks as though to extend your application that you'll have to modify a giant switch, if/else block.
Perhaps a strategy pattern could help break your algorithm apart. But it depends.
Edit:
From LiWa's additional example of needing to vary the inputs, here is a useful blog post describing refactoring a switch statement into separate algorithms: Applying Strategy Pattern Instead of Using Switch Statements
如果将几个输入变量封装在单个类中,字典仍然可以很好,它具有适当的相等语义,包括哈希代码(您必须始终定义与您的相等语义兼容的哈希代码语义)。
I've found some pattern usefull in past, not cover all cases, but you can found something here...
resource from constant
When you have one or more output as function of a single value (as a switch) you can use resources.
return ResourceNamespace.ResxFileName.ResourceManager.GetString("ResourceKey")
String combination: when the result can be determined with a "concatenation" of codes you can drop in resources
public string Decode(string a, string b, string c)
{
return ResourceNamespace.ResxFileName.ResourceManager.GetString(a + b + c);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.