将switch case转为条件驱动

switch case是一种.net里面常用的条件分支语句,挺好用的;不过有些缺点:

1.在有包含大量条件和执行语句的时候代码结构会很乱。

2.不太符合面对对象的设计原则。

3.对于查询条件是否满足一定范围这样的逻辑不太好用。
 

 

将其转为条件驱动的实现,(本例使用Dictionary+Delegate的方式)

View Code
    class SwitchTest
{
/// <summary>
/// 常规写法
/// </summary>
/// <param name="type"></param>
public static void Test(EnumType type)
{
switch (type)
{
case EnumType.A:
break;
case EnumType.B:
break;
case EnumType.C:
break;
case EnumType.D:
break;
case EnumType.E:
break;
case EnumType.F:
break;
case EnumType.G:
break;
case EnumType.H:
break;
case EnumType.I:
break;
case EnumType.J:
break;
case EnumType.K:
break;
default:
break;
}
}


#region 下面所有的代码是另一种实现方法. 关键是handlers的初始化
static Dictionary<EnumType, Action<object>> handlers = new Dictionary<EnumType, Action<object>>();
static SwitchTest()
{
var methods = typeof(SwitchTest).GetMethods();
var fields = Enum.GetNames(typeof(EnumType)).ToList();
foreach (var item in methods)
{
if (item.Name.StartsWith("Handle"))
{
var commandTypeName = item.Name.Substring(6, item.Name.Length - 6);
if (fields.Contains(commandTypeName))
{
EnumType type = (EnumType)Enum.Parse(typeof(EnumType), commandTypeName);
handlers[type] = (Action<object>)Delegate.CreateDelegate(typeof(Action<object>), item);
}
}
}

//也可以通过下面的代码,初始化Dictionary
//handlers[EnumType.A] = new Action<object>(HandleA);
//handlers[EnumType.B] = new Action<object>(HandleB);
//handlers[EnumType.C] = new Action<object>(HandleC);
// ....

//当然 也可以通过其他逻辑初始化Dictionary
}

/// <summary>
/// 使用Dictionary 加上 Delegate的写法
/// </summary>
/// <param name="enumType"></param>
internal static void Test2(EnumType enumType)
{
//如果要设计为可以处理一定范围的逻辑, 可以在这里添加一个方法处理输入值,例如1-20的值都认为是处理逻辑A

if (handlers.ContainsKey(enumType))
{
handlers[enumType](null);
}
else
{
//默认处理逻辑
}
}

public static void HandleA(object obj)
{
}
public static void HandleB(object obj)
{
}
public static void HandleC(object obj)
{
}
public static void HandleD(object obj)
{
}
public static void HandleE(object obj)
{
}
public static void HandleF(object obj)
{
}
public static void HandleG(object obj)
{
}
public static void HandleH(object obj)
{
}
public static void HandleI(object obj)
{
}
public static void HandleJ(object obj)
{
}

#endregion
}

/// <summary>
/// 用于演示的枚举类型
/// </summary>
public enum EnumType
{
A = 1,
B = 2,
C = 3,
D = 4,
E = 5,
F = 6,
G = 7,
H = 8,
I = 9,
J = 10,
K = 11,
}

 

1.常用的委托有Action<T> 和 Func<T>

2.也可以自己定义委托以支持任意方法

3.可以传递Delegate的方式实现更为复杂的多重逻辑

4.毫无疑问,在简单的情况下不是很使适用条件驱动这样相对复杂的方案
 

 

关于性能问题:

            //准备数据
Random random = new Random();
int length = 1000000;
EnumType[] testData = new EnumType[length];
for (int i = 0; i < length; i++)
{
testData[i] = (EnumType)Enum.Parse(typeof(EnumType), random.Next(1, 11).ToString());
}

Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < testData.Length; i++)
{
SwitchTest.Test(testData[i]);
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);//13 执行100万次


sw.Restart();
for (int i = 0; i < testData.Length; i++)
{
SwitchTest.Test2(testData[i]);
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);//62 执行100万次

 

执行10万次分别消耗9毫秒 和7毫秒,

执行100万次分别消耗13毫秒 和62毫秒,

(可能有点误差,不过这样小的消耗主要是为了表明其实两种写法的性能权重都不高)

 

好久之前的东西了。。。最近正好又遇到,就记录在blog中,顺便看看有没有什么可以优化的地方

 

posted on 2011-12-04 16:53  听说读写  阅读(3058)  评论(2编辑  收藏  举报

导航