我在后面的代码中有三次与此示例非常相似的代码。 每次交换机切换到发送给它的选项。每 除了参数之外,案例中的代码完全相同 基于案例。是使用开关/案例和方法的最佳方式 去做这个?我是否应该考虑使用某种类型的设计模式来避免重复开关/案例结构?
string option = dropDownList.SelectedValue.ToString();
switch (option.ToUpper())
{
case "ALPHA":
// do repeative code method here; only change is a parameter
break;
case "BRAVO":
// do repeative code method here; only change is a parameter
break;
case "CHARLIE":
// do repeative code method here; only change is a parameter
break;
case "DELTA":
// do repeative code method here; only change is a parameter
break;
default:
break;
}
答案 0 :(得分:11)
您可以构建一个表格,将string
转换为parameter value
。
var lookup = new Dictionary<string, ParaType> ()
{
{ "ALPHA", a },
{ "BETA", b },
....
};
ParaType para;
if (lookup.TryGetValue(option, out para)) // TryGetValue, on popular request
{
// do repeative code method here; with para
}
答案 1 :(得分:11)
编译器非常擅长优化开关/案例结构; CLR可能会把它变成查询表或类似的快速,所以手动滚动自己的版本,如Henk Holterman建议不是我推荐的。在选择最佳算法时,CLR可以做得更好。
如果这是一个优雅或可维护性的问题,并且你有几个关于同一个类执行类似功能的交换机/案例,那么改进它的一种方法是将与单个“案例”相关的所有功能封装到其中自己的类实例,如下所示:
class MyOption
{
public static readonly MyOption Alpha = new MyOption(1, 10, "Alpha Text");
public static readonly MyOption Bravo = new MyOption(2, 100, "Bravo Text");
public static readonly MyOption Charlie = new MyOption(3, 1000, "Charlie Text");
// ... Other options ...
public static readonly MyOption Default = new MyOption(0, 0, null);
public MyOption(int id, int value, string text)
{
this.ID = id;
this.Value = value;
this.Text = text;
}
public int ID { get; private set; }
public int Value { get; private set; }
public string Text { get; private set; }
}
然后在你的班级/控制/页面中:
static MyOption GetOption(string optionName)
{
switch (optionName)
{
case "ALPHA":
return MyOption.Alpha;
case "BRAVO":
return MyOption.Bravo;
case "CHARLIE":
return MyOption.Charlie;
// ... Other options ...
default:
return MyOption.Default;
}
}
private MyOption GetOptionFromDropDown()
{
string optionName = GetOptionNameFromDropDown();
return GetOption(optionName);
}
private string GetOptionNameFromDropDown()
{
// ... Your code ...
}
之后,您可以开始制作事件和其他方法:
private void control1_SomeEvent(object sender, EventArgs e)
{
MyOption option = GetOptionFromDropDown();
DoSomething(option.ID);
}
private void control2_SomeEvent(object sender, EventArgs e)
{
MyOption option = GetOptionFromDropDown();
DoSomethingElse(option.Value);
}
当然,如果您想要将这些开关/案例中的几个重构为一个,这只是一个有用的模式。如果您只有一个交换机/机箱,那么您最终会以这种方式获得更多更多代码,所以请不要管它!
提高可维护性的其他可能性包括:
就是这样。它编写简单,易于理解,易于维护,如果您有大量的开关/案例结构,它将节省您的时间,并且它仍然允许CLR执行最佳的优化。唯一的成本是保存那些只读字段所需的少量内存。
答案 2 :(得分:3)
我想我会将switch语句移动到一个单独的函数中并让它为每种情况返回参数值:
private static string GetParameterForAllCases(string option)
{
switch (option.ToUpper())
{
case "ALPHA":
return "ALPHA Parameter";
case "BRAVO":
return "BRAVO Parameter";
case "CHARLIE":
return "CHARLIE Parameter";
case "DELTA":
return "DELTA Parameter";
default:
return "Default Parameter";
}
}
然后你可以调用你的工作方法一次:
string option = dropDownList.SelectedValue.ToString();
WorkMethod(GetParameterForAllCases(option);
如果您不想为默认原因执行工作方法,或者您有多个参数值,则可以更改GetParameter方法以使用输出参数:
private static bool GetParameter(string option, out string value)
{
switch (option.ToUpper())
{
case "ALPHA":
value = "ALPHA Parameter";
return true;
case "BRAVO":
value = "BRAVO Parameter";
return true;
case "CHARLIE":
value = "CHARLIE Parameter";
return true;
case "DELTA":
value = "DELTA Parameter";
return true;
default:
value = null;
return false;
}
}
并称之为:
string option = dropDownList.SelectedValue.ToString();
string value;
if (GetParameter(option, out value))
WorkMethod(value);
答案 3 :(得分:2)
此问题的关键是使存储在dropDownList中的对象提供参数(直接或通过索引到数组中)。然后可以完全删除switch语句。
如果参数是下拉列表中显示的对象的属性,那么这将非常有效地提供该值。
如果下拉列表中的值可以为参数值数组提供数字索引,那么这将在运行时效率方面击败一系列字符串比较。
这些选项中的任何一个都比打开字符串更清晰,更短,更容易维护。
答案 4 :(得分:1)
也许从选项转换为方法参数?
这将允许您删除switch语句并简单地为方法提供转换后的参数。
答案 5 :(得分:0)
这对你正在做的事情来说可能有点过头了,但代码可以最终更清洁。
class AlphabetChar
{
public virtual void DoSomething(){}
}
class Alpha : AlphabetChar {}
class Bravo : AlphabetChar {}
...
class AlphabetCharFactory
{
public static AlphabetChar GetByName(string name)
{
switch (name.ToUpper())
{
case "ALPHA":
return new Alpha();
...
default:
//google for "wiki null object"
return new NullAlphabetChar();
}
}
}
然后调用代码变为......
string option = dropDownList.SelectedValue.ToString();
AlphabetChar alphabetChar = AlphabetCharFactory.GetByName(option);
alphabetChar.DoSomething();
就像我说的,如果你所做的只是设置一个参数(基本上是从子类中设置基类中的属性),那就太过分了。但如果你的逻辑更复杂,这对你来说可能是一个可行的选择。
答案 6 :(得分:0)
var processingValues = new Dictionary<string, Func<string, string>>() {
{"ALPHA", yourProcessor.Alpha},
{"BRAVO", yourProcessor.Bravo},
...
}
之后,您可以为ALPHA,BRAVA,......创建功能。
public class Processor
{
public string Alpha(string data)
{
return "do something";
}
public string Bravo(string data)
{
return "do something";
}
...
}
最后返回一些函数:
public string SomethingToReturn(string key, string value)
{
if (proccessValues.ContainsKey(name))
{
return proccessValues[name].Invoke(value);
}
return string.Empty;
}
希望有所帮助。