3

With all the awesome stuff we can do in C#, I was wondering if we could do something like the below:

  string totalWording =
  {
    if (isA)
      return "Value A";

    if (isB)
      return "Value B";

    if (isC)
      return "Value C";

    return "Default";
  };

So this would be very similar to the ?: except you can have more than 2 possible outcomes

string totalWording = isA ? "Value A" : "Default";

I could happily create a method that returns the value, but I'm a big fan of being able to see the simple stuff straight away

private string GetTotalWording()
{
  if (isA)
    return "Value A";

  if (isB)
    return "Value B";

  if (isC)
    return "Value C";

  return "Default";
}

I'd like to hear if anybody has something nice I can use, or if I'm just living on a prayer.

Edit:

There is the func option too, which is what I suppose got me onto the topic, as it looks you should be able to straight-up use a function when declaring a value.. but that might just be me

    Func<string> getTotalWording = () =>
    {
      if (isA)
        return "Value A";

      if (isB)
        return "Value B";

      if (isC)
        return "Value C";

      return "Default";
    };
Oyyou
  • 610
  • 5
  • 13
  • A statement is either true or false, in your method you are checking 3 different bools, I could convert your GetTotalWording to a ternary(?:) expression quite easily but I don't think its what you're looking for. Should the result be `Value A` if all 3 are true for instance? – EpicKip Sep 26 '17 at 11:02
  • What if `isA` and `isC` are both true, or is it only possible for one to be true at any given time? – Equalsk Sep 26 '17 at 11:03
  • Or does he want just to take the first thing that's true, regardless of whether the later ones are true? – Matthew Watson Sep 26 '17 at 11:04
  • The logic I've been supplied is hierarchical, so whatever comes first is used. – Oyyou Sep 26 '17 at 11:08
  • In which case the nested ternary shown by Amit will do this, but going for "clever" one liners over simple, readable code is a common mistake. – Equalsk Sep 26 '17 at 11:10
  • You can have nested functions nowadays, perhaps that would help? Do you just want to keep the logic inside one method? You could nest the function in that method. – Matthew Watson Sep 26 '17 at 11:13
  • I was thinking that - I'll edit it my post so we can all see the option. But yes, this logic is only being used once. – Oyyou Sep 26 '17 at 11:14
  • @Oyyou Updated an enum sample as well. Do check. – Amit Kumar Singh Sep 26 '17 at 11:44

2 Answers2

3

Use repetitions of ternary operator.

string totalWording = isA ? "Value A" : (isB ? "Value B" : (isC ? "Value C" :  "Default"))

There is another way, if you only have manage-able number of if's and they remain same always. Create an enum with string values.

Below answer is based on another on Stack Overflow

You can create an enum for these statements with description.

public enum Values
    {
        [Description("Value A")] A,
        [Description("Value B")] B,
        [Description("Value C")] C,
        [Description("Value D")] D
    }

Then, you can create a function to get enum description

private static string GetEnumDescription(string text)
{
    var valueAttribs = typeof(Values).GetMember(text)[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
    return ((DescriptionAttribute)valueAttribs[0]).Description;
}

and you can then use these as

var variable = "A";

    string description = 
      (Enum.IsDefined(typeof(Values), variable)) ? 
          GetEnumDescription(variable) : "Default";

    Console.WriteLine(description);
    Console.ReadLine();
Amit Kumar Singh
  • 4,393
  • 2
  • 9
  • 22
  • Oh damn, son. I was thinking of something like that, but it didn't quite come out. Interesting. I'll see if anything else comes up before marking as answer. – Oyyou Sep 26 '17 at 11:05
  • @MatthewWatson, if I were to take this route - I'd be splitting with lines. The logic I'm currently using isn't too overwhelming. – Oyyou Sep 26 '17 at 11:06
  • @Oyyou Seriously though, don't do this. It's so unreadable compared to the first version. (And splitting it with lines doesn't really give you any advantage over the original easy-to-read-and-understand version.) – Matthew Watson Sep 26 '17 at 11:06
  • I think I have used this in the past (when just learning the ?: operator), and it did look nasty. For the time being, I'll be sticking with the get method. Unless of course, somebody comes up with something magical. – Oyyou Sep 26 '17 at 11:11
2

You could nest the method and lay it out more succinctly, so it looks more like this:

void someMethod(bool isA, bool isB, bool isC)
{
    string totalWording() {
        if (isA) return "Value A";
        if (isB) return "Value B";
        if (isC) return "Value C";
        /*Else*/ return "Default"; }

    // Other code...

    string s = totalWording();

    // Etc
}

I personally find that more readable.

If you can't use C# 7 you can do a similar thing with a Lambda in earlier versions, as you've already noted in your question. I'll put a copy here for completeness:

void someMethod(bool isA, bool isB, bool isC)
{
    Func<string> totalWording = () => {
        if (isA) return "Value A";
        if (isB) return "Value B";
        if (isC) return "Value C";
        /*Else*/ return "Default"; };

    // Other code...

    string s = totalWording();

    // Etc
}

The reason I strongly prefer this to the version using the ternary operator is that when reading the ternary version I have to mentally translate it into the above code when trying to understand it.

If I have to do that, then I'd rather it was written down for me so I didn't need to expend the effort. Perhaps that's just me, and I'm lazy. ;)

Matthew Watson
  • 104,400
  • 10
  • 158
  • 276