如何用 Dictionary<string, Func<>> 替换这个 switch - case?
How to replace this switch - case with a Dictionary<string, 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
}
我想将 MyIntArgsFunction 和 MyStringArgsFunction 这两个函数添加到 Dictionary> 结构中,然后根据用户选择的颜色调用适当的函数。但是由于他们的论据不同,我无法为 Func 委托得出合适的签名。
有人可以帮忙吗?
尼哈尔
看起来很糟糕,但它确实有效:)
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);
}
}
学者会建议 "Object Oriented" 方法。
可悲的是,工厂模式需要一个开关盒,你说你 "Hate switch cases" 尽管最好也说明具体原因。
我想这一切都与代码清晰度和 "Case" 插件可用性有关
这是我避免 switch case 的方法。
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;
}
}
您也可以更改结构以支持批处理。
Handlers 是值的默认初始化。
如果您想覆盖这些值,InitHandler 是一个函数。
https://elegantcode.com/2009/01/10/refactoring-a-switch-statement/
作者 Chris Brandsma 提供了另一种使用基于字典的工厂的有用方法。另请注意 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 “
我讨厌开关盒。我正在尝试在我的代码中重构一个 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
}
我想将 MyIntArgsFunction 和 MyStringArgsFunction 这两个函数添加到 Dictionary> 结构中,然后根据用户选择的颜色调用适当的函数。但是由于他们的论据不同,我无法为 Func 委托得出合适的签名。
有人可以帮忙吗?
尼哈尔
看起来很糟糕,但它确实有效:)
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);
}
}
学者会建议 "Object Oriented" 方法。 可悲的是,工厂模式需要一个开关盒,你说你 "Hate switch cases" 尽管最好也说明具体原因。 我想这一切都与代码清晰度和 "Case" 插件可用性有关 这是我避免 switch case 的方法。
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;
}
}
您也可以更改结构以支持批处理。 Handlers 是值的默认初始化。 如果您想覆盖这些值,InitHandler 是一个函数。
https://elegantcode.com/2009/01/10/refactoring-a-switch-statement/
作者 Chris Brandsma 提供了另一种使用基于字典的工厂的有用方法。另请注意 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 “