简体   繁体   中英

Best way to handle constant data? (C#)

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.

As a general note:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM