如何替换此开关 - 使用Dictionary <string,func <=“”>&gt;?

时间:2015-11-30 14:15:06

标签: c# refactoring func

我讨厌开关 - 案件。我试图在我的代码中重构一个switch - case,如下所示:

int i = 0;
string str = string.empty;

switch (color)
{
    case "red":
        i = MyIntArgsFunction(1, 2);

    case "blue":
        str = MyStringArgsFunction("cat", "dog");
}


private int MyIntArgsFunction(int x, int y)
{
    // Implementation
}

private string MyStringArgsFunction(string s, string t)
{
    // Implementation
}

我想将2个函数MyIntArgsFunction和MyStringArgsFunction添加到Dictionary&gt;结构,然后根据用户选择的颜色调用适当的函数。但由于参数不同,我无法为Func代表找到合适的签名。

有人可以帮忙吗?

尼哈尔

3 个答案:

答案 0 :(得分:1)

它看起来像地狱,但它有效:)

    private static void Main(string[] args)
    {
        var blueHandler = new Action<string, string>((x, y) => { });
        var redHandler = new Action<int, int>((x, y) => { Console.WriteLine(x);});

        var redStr = "Red";
        var blueStr = "Blue";

        var colorSelector = new Dictionary<string, Invoker>();
        var a = 10;
        var b = 20;
        colorSelector.Add(redStr, new Invoker(redHandler, a, b));
        colorSelector.Add(blueStr, new Invoker(blueHandler, a, b));

        colorSelector["Red"].Invoke();
    }

    public class Invoker
    {
        private Delegate _handler;
        public object[] _param;
        public Invoker(Delegate handler, params object[] param)
        {
            _param = param;
            _handler = handler;
        }

        public void Invoke()
        {
            _handler.DynamicInvoke(_param);
        }
    }

答案 1 :(得分:1)

学者会建议&#34;面向对象&#34;方法。 可悲的是,工厂模式需要一个开关盒,你声称你是“讨厌开关盒”#34;虽然说明具体原因也是明智之举。 我想这完全是关于代码清晰度和&#34; Case&#34;插上可用性 这是我避免切换案例的方法。

public abstract class ColorHandler
{
    public String str { get; set; }
    public int i { get; set; }
    public abstract void Handle();
    public static ColorHandler ColorHandlerFactory(String color,ref int i, ref string str)
    {
        ColorHandler handler = Handlers[color];
        handler.i = i;
        handler.str = str;
        handler.Handle();
        return handler;
    }
    public static Dictionary<String, ColorHandler> Handlers = new Dictionary<string, ColorHandler> ()
    {
        {"red",new RedHandler{myInt1 = 1,myInt2 =2,}},
        {"blue",new BlueHandler{MyStr1="str1",MyStr2="str2"} }
    };
    public Dictionary<String, ColorHandler> InitHandlers(int myNum1,int myNum2,string myStr1,string myStr2){
        return new  Dictionary<string, ColorHandler>()
    {
        {"red",new RedHandler{myInt1 = myNum1,myInt2 =myNum2}},
        {"blue",new BlueHandler{MyStr1=myStr1,MyStr2=myStr2} }
    };
    }

}
public class RedHandler : ColorHandler
{
    public int myInt1 { get; set; }
    public int myInt2 { get; set; }
    public override void Handle()
    {
        this.i = myInt1+myInt2;
        // OR alternatively
        //this.myInt1 = AnExternalFunction(myInt1, myInt2);
    }
}
public class BlueHandler : ColorHandler
{
    public String MyStr1 { get; set; }
    public String MyStr2 { get; set; }
    public override void Handle()
    {
        this.str = MyStr1 + MyStr2;
        // OR alternatively
        //this.myInt1 = AnExternalFunction(MyStr1, MyStr2);
    }
}

public class Doer
{
    public void DoThings()
    {
        int i = 0;
        string str = string.Empty;
        var handler =ColorHandler.ColorHandlerFactory("red",ref i,ref str);
        handler.InitHandlers(1, 2, "Cat", "Dog");
        //Read Results.
        var result=handler.i;


    }
}

您也可以更改结构以支持批处理。 处理程序是值的默认初始化。 并且InitHandler是一个函数,以防您想要覆盖这些值。

答案 2 :(得分:1)

https://elegantcode.com/2009/01/10/refactoring-a-switch-statement/

作者Chris Brandsma提供了另一种使用基于字典的Factory的有用方法。另请注意,Henrik Gustafsson的评论为工厂实现提供了一种多态方法。

根据亨里克·古斯塔夫森(Henrik Gustafsson):

“通常可以通过小心地使用多态来替换switch语句。如果重构时将switch语句作为方法中的唯一内容,并且switch语句中的每个条目仅调用另一个方法,则状态为每种情况和每种方法通常都可以分为自己的子类。此外,您可以降低循环复杂度

转向

class X {
void m() {
switch(…) {
case A:
m_A();
break;
…
}
}
}

进入

class X {
IM _m;
void m() {
_m.dostuff();
}
}

interface IM {
void dostuff();
}

class MA extends IM {
public void dostuff() {
…
}
}

这当然很冗长,所以我以前发现自己使用了dict技巧的变体。

Misko Hevery在此Google技术讲座中对此有一些有趣的见解:http://www.youtube.com/watch?v=4F72VULWFvc