简体   繁体   中英

C# Avoid Multiple SWITCH Statements .net

Please excuse bursts of stupidity as I learn the intricacies of C# / .NET

Say I have three classes with multiple static properties (more than three but for arguments sake..)

 CLASS FOO

    public static A
    { 
       get / set A;
    }   
    public static B
    {
       get / set B;
    }   
    public static C
    {
       get / set C;
    }   

 CLASS BAR
     {
        get / set A;
     }
    public static B
    {
       get / set B;
    }   
    public static C
    {
       get / set C;
     }   

 CLASS YOO
     {
        get / set A;
     }
    public static B
    {
       get / set B;
     }   
    public static C
    { 
       get / set C;
    }   

And from another class I need to update one or several static properties in each class multiple times... How do I keep from writing multiple SWITCH statments like this...

 public void updateVarx(string class, string varx)
 {
   string y = 'class'
   SWITCH (y)
   {
      case FOO:
       FOO.A = Varx;
       break;
      case BAR:
       BAR.A = Varx;
       break;
      case YOO:
       YOO.A = Varx;
      break;
   }
 }

And then another one when I want to update B varY:

 public void updateVary(string class, string vary)
 {
   string y = 'class'
   SWITCH (y)
   {
     case FOO:
      FOO.B = Vary;
      break;
     case BAR:
      BAR.B = Vary;
      break;
    case YOO:
      YOO.B = Vary;
      break;
   }
 }

Since you are learning .net/c#, I guess i should warn you, using static properties is probably not the way to go in object oriented programming.

Static is global state and is dangerous. If you end up using multi-threaded code, you have to be super careful. If you need only one instance, just instantiate one, but don't go creating static properties on a class, unless you have a pretty good reason to add them (And I can't think of any right now).

In fact, in well designed, object oriented code you sould probably not have many if, switch, getters or setters either.

Let's say you need different behaviors on your classes, you can do it this way.

Interface ISecurity {
  void UpdateVarX(int value);
  void UpdateVarY(int value);
  int GetValueX();
  int GetValueX();
}

class Foo:ISecurity {
  // Implement methods of the interface
}

class Bar:ISecurity {
  // Implement methods of the interface
}

class Yoo:ISecurity {
  // Implement methods of the interface
}

// This class is the class that uses your other classes
class Consumer 
{
  private ISecurity sec;

  public Consumer(ISecurity sec) {
    sec.UpdateVarX(25);
  }
}

Or if as in your example, all your static classes have the same properties:

public class Settings {
  public int A {get; set;}
  public int B {get; set;}
  public int C {get; set;}
}

public class NeedsToUseOtherClass {
  public NeedsToUseOtherClass() {
    Settings foo = new Settings();
    Settings bar = new Settings();
    Settings yoo = new Settings();

    foo.setA(25);
  }
}

Maybe I am not understanding the problem but if all your classes have the same exact properties then you can just pass the object (FOO, BAR, or YOO) into UpdateVarx or UpdateVary methods and just implement an interface? Something along these lines:

public class FOO : IHasStatus
{
    public A
    { 
       get / set A;
    }   
    public B
    {
       get / set B;
    }   
    public C
    {
       get / set C;
    }
} 

public void updateVarx(IHasStatus someObject, string varx)
{
    someObject.A = varx;
}
public void updateVary(IHasStatus someObject, string vary)
{
    someObject.B = vary;
}

If you don't need the concrete classes, you can abstract out the logic like so:

public class Status {
    public string A {
        get; set;
    }

    public string B {
        get; set;
    }

    public string C {
        get; set;
    }
}

public static class StatusManager {
    private static Dictionary<string, Status> statusMap = new Dictionary<string,Status>();

    public static Status GetStatus(string name) {
        Status status;
        if (!statusMap.TryGetValue(name, out status))
            statusMap[name] = status = new Status();
        return status;
    }

    public static void SetStatus(string name, Status status) {
        statusMap[name] = status;
    }

    public static void UpdateVarx(string name, string varx) {
        GetStatus(name).A = varx;
    }

    // ...
}

If you are a fan of the javascript way of solving multiple switch cases like this

you can always wrap up the switch handlers as Actions and toss them in a Dictionary.

For example : (Source obtained from here )

   public class SwitchCase : Dictionary<string,Action>
    {
        public void Eval(string key)
        {
            if (this.ContainsKey(key))
              this[key]();
            else
             this["default"](); 
        }
    }


    //Now, somewhere else

            var mySwitch = new SwitchCase
            {
                { "case1",  ()=>Console.WriteLine("Case1 is executed") },
                { "case2",  ()=>Console.WriteLine("Case2 is executed") },
                { "case3",  ()=>Console.WriteLine("Case3 is executed") },
                { "case4",  ()=>Console.WriteLine("Case4 is executed") },
                { "default",()=>Console.WriteLine("Default is executed") },
            };

            mySwitch.Eval(c);

Below code uses all kinds of hacks, not really recommended in production code unless you have a very good reason.

using System;
using System.Linq;

namespace ConsoleApplication1
{
    static class Program
    {
        private static void SetStaticProperty(string className, string propName, string varx)
        {
            //This sucks, I couldnt find the namespace with easily through reflection :(
            string NAMESPACE = "ConsoleApplication1";
            Type t = Type.GetType(NAMESPACE + "." + className);
            t.GetProperties().Where(p => p.Name == propName).First().SetValue(null, varx, null);
        }

        public static void updateVarx(string className, string varx)
        {
            SetStaticProperty(className, "A", varx);
        }

        public static void updateVary(string className, string vary)
        {
            SetStaticProperty(className, "B", vary);
        }

        static void Main(string[] args)
        {
            updateVarx("Foo", "FooAstring");
            updateVarx("Bar", "BarAstring");
            updateVarx("Yod", "YodAstring");
            updateVary("Foo", "FooBstring");
            updateVary("Bar", "BarBstring");
            updateVary("Yod", "YodBstring");

            Console.WriteLine(Foo.A);
            Console.WriteLine(Foo.B);
            Console.WriteLine(Bar.A);
            Console.WriteLine(Bar.B);
            Console.WriteLine(Yod.A);
            Console.WriteLine(Yod.B);
            Console.ReadLine();
        }
    }

    class Foo
    {
        public static string A { get; set; }
        public static string B { get; set; }
        public static string C { get; set; }
    }

    class Bar
    {
        public static string A { get; set; }
        public static string B { get; set; }
        public static string C { get; set; }
    }

    class Yod
    {
        public static string A { get; set; }
        public static string B { get; set; }
        public static string C { get; set; }
    }
}

You can use dictionary as configuration and remove the switch statement Create a dictionary and add append data as below for mapping

//Have dictionary setted up
Dictionary<string, dynamic> m_Dictionary = new Dictionary<string, dynamic>();
m_xmlDictionary.Add("classA",FOO);
m_xmlDictionary.Add("classB",BAR);
m_xmlDictionary.Add("classC",BAR);
//Have dictionary setted up


//change the function as below
public void updatevarx(string class, string varx)
{
    m_Dictionary[class].A=varx // Replaced switch statement
}

//while calling use
updatevarx("classC","abc!");// This will assign BAR.A with abc!

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