user610217
user610217

Reputation:

I want something like the switch statement (but different of course)

Is there a C# construct like the switch statement that allows control to fall through the next level? I have something like this:

    public static IEnumerable<string> SeverityOrHigher(string severity)
    {
        var result = new List<string>();

        switch (severity.ToUpper())
        {
            case "ALL":
                result.Add("ALL");
            case "DEBUG":
                result.Add("DEBUG");
            case "INFO":
                result.Add("INFO");
            case "WARN":
                result.Add("WARN");
            case "ERROR":
                result.Add("ERROR");
            case "FATAL":
                result.Add("FATAL");
            case "OFF":
                result.Add("OFF");
            default:
                break;
        }

        return result;
    }

...which clearly does not work in C#, (Control cannot fall through from one case label...) yet it seems to me like it should. I know it expects breaks in there, but that would not give me the data flow I'm looking for. What can be done to make this happen the way I'd like?

Upvotes: 3

Views: 483

Answers (7)

Nesim Razon
Nesim Razon

Reputation: 9794

@nemesv's Linq answer is way better solution but if you want to do it with switch you could do like this and will get same result.

public static IEnumerable<string> SeverityOrHigher(string severity)
{
  var lastFound = -1;

  var severityList = new List<string>() { "ALL", "DEBUG", "INFO", "WARN", "ERROR", "FATAL", "OFF" };
  var results = new List<string>();

  foreach (var t in severityList)
  {

    if (lastFound > -1)
    {
      for (var index = lastFound + 1; index < severityList.Count; index++)
      {
        results.Add(severityList[index]);
      }
      return results;
    }

    switch (severity.ToUpper())
    {
      case "ALL":
        results.Add(severity);
        lastFound = 0;
        break;
      case "DEBUG":
        lastFound = 1;
        results.Add(severity);
        break;
      case "INFO":
        lastFound = 2;
        results.Add(severity);
        break;
      case "WARN":
        lastFound = 3;
        results.Add(severity);
        break;
      case "ERROR":
        lastFound = 4;
        results.Add(severity);
        break;
      case "FATAL":
        lastFound = 5;
        results.Add(severity);
        break;
      case "OFF":
        lastFound = 6;
        results.Add(severity);
        break;
    }
  }

  return results;
}

Test:

  var list = SeverityOrHigher("ALL");
  foreach (var severity in list)
  {
    Console.WriteLine(severity);
  }

  Console.ReadKey();

Upvotes: 1

Matthew Abbott
Matthew Abbott

Reputation: 61589

Along with gotos, etc, you could do with this an enum and a bit of linq:

    public static IEnumerable<Severity> SeverityOrHigher(Severity severity)
    {
        var value = (int) severity;

        return Enum.GetValues(typeof (Severity))
            .Cast<int>()
            .Where(i => i >= value)
            .Select(i => (Severity) i);
    }

    public enum Severity
    {
        All = 0,
        Trace = 1,
        Debug = 2,
        Information = 3,
        Warning = 4,
        Error = 5,
        Fatal = 6
    }

Upvotes: 2

Ian Newson
Ian Newson

Reputation: 7949

Use goto:

        switch (severity.ToUpper())
        {
            case "ALL":
                result.Add("ALL");
                goto case "DEBUG";
            case "DEBUG":
                result.Add("DEBUG");
                goto case "INFO";
            case "INFO":
                result.Add("INFO");
                goto case "WARN";
            case "WARN":
                result.Add("WARN");
                goto case "ERROR";
            case "ERROR":
                result.Add("ERROR");
                goto case "FATAL";
            case "FATAL":
                result.Add("FATAL");
                goto case "OFF";
            case "OFF":
                result.Add("OFF");
                break;
            default:
                break;
        }

Microsoft (implicitly) recommends this use: http://msdn.microsoft.com/en-us/library/06tc147t(v=vs.71).aspx

Upvotes: 1

Itamar Marom
Itamar Marom

Reputation: 525

I'd go with somehting like creating another list which represents all valid severities and checking if the input severity is one of them:

public static IEnumerable<string> SeverityOrHigher(string severity)
{
    var result = new List<string>();
    var severities = new List<string> { "ALL", "DEBUG", "INFO", "WARN", "ERROR", "FATAL", "OFF" };

    severity = severity.ToUpper();

    if (severities.Contain(severity))
            result.Add(severity);

    return result;
}

Upvotes: 0

Xharze
Xharze

Reputation: 2733

It is not the optimal solution but you could use the goto statement like this:

switch (severity.ToUpper())
{
  case "ALL":
    result.Add("ALL");
    goto case "DEBUG";
  case "DEBUG":
    result.Add("DEBUG");
    goto case "INFO";
  case "INFO":
    result.Add("INFO");
    goto case "WARN";
  case "WARN":
    result.Add("WARN");
    goto case "ERROR";
  case "ERROR":
    result.Add("ERROR");
    goto case "FATAL";
  case "FATAL":
    result.Add("FATAL");
    goto case "OFF";
  case "OFF":
    result.Add("OFF");
    break;
  default:
    break;
}

Upvotes: 1

nemesv
nemesv

Reputation: 139758

In your case you can emulate "falling case" with a little bit of LINQ:

public static IEnumerable<string> SeverityOrHigher(string severity)
{
    var result = new List<string>() 
        { "ALL", "DEBUG", "INFO", "WARN", "ERROR", "FATAL", "OFF" };
    return result.SkipWhile(l => l != severity.ToUpper()).ToArray();
}

Upvotes: 10

Yogu
Yogu

Reputation: 9445

Does not look very nice, but could do the job for you:

string s = severity.ToUpper();
result.add("OFF");
if (s == "OFF")
  return result;
result.add("FATAL");
if (s == "FATAL")
  return result;
result.add("ERROR");
if (s == "ERROR")
  return result;
// ...
result.add("ALL");
return result;

Upvotes: 0

Related Questions