C#中 enum 和 常量 的可靠编程

查看微软的C#参考中enum介绍的时候,冒出来下面一段:
 
 
与任何常量一样,对枚举中各个值的所有引用在编译时均将转换为数值文本。 这可形成潜在的版本控制问题,如常量(C# 编程指南)中所述。

给新版本的枚举赋其他值,或者更改新版本中枚举成员的值,可导致相关源代码出现问题。 通常在 switch 语句中使用枚举值。 如果 enum 类型中添加了其他元素,则 switch 语句的默认节可能被意外选定。

如果其他开发人员使用您的代码,则需要提供相关说明,告诉开发人员如果任何 enum 类型中添加了新元素,他们的代码应该如何响应。

 

这是什么鬼??

仔细琢磨琢磨,可能存在下面这种情况:

一个程序集A中,定义了一些常量:

 public const int TableA = 1;
 public const int TableB = 3;
 public const int TableE = 4;

这些常量在另一个程序集B中被引用:

        switch (iTable)
        {
            // TableA
            case TableA:
                dosomething();
                break;
            // TableB
            case TableB:
                dosomething();
                break;
            // TableE
            case TableE:
                dosomething();
                break;
            // 默认
            default:
                dosomething();
                break;
        }

 

这段代码通过变量iTable对不同Table作不同处理。

到现在一切很好,没什么问题。

有一天可能有些需求变动或某人纯粹出于不爽,把程序集A变动了一下,如下:

public const int TableA = 1;
public const int TableB = 2;
public const int TableC = 3;
public const int TableD = 4;
public const int TableE = 5;

编译过后,直接替换了程序集B项目中需要的程序集A的*.dll,运行一下,没有报错。嘿!一切OK!!

我们回头看看这一句:与任何常量一样,对枚举中各个值的所有引用在编译时均将转换为数值文本。

这是什么意思??

其实就是这个意思,程序集B编译后的代码等效于如下代码:

        switch (iTable)
        {
            // TableA
            case 1:
                dosomething();
                break;
            // TableB
            case 2:
                dosomething();
                break;
            // TableE
                case 5:
                dosomething();
                break;
            // 默认
            default:
                dosomething();
                break;
        }

 

这时,问题就来了:

  • iTable为TableA值的时候,没错,程序进入case 1
  • iTable为TableB值的时候,程序进入default;(为什么?因为TableB 的值被改为 2 了,没有这个分支。)
  • iTable为TableE值的时候,程序还是进入default;(理由与TableB一样。)

这就是C#参考里那一段要表达的真正含义。解决这个问题也简单:程序集B项目引用的dll文件有更新的时候,最好重新编译一下。

重新编译后的程序集B等效如下代码:

        switch (iTable)
        {
            // TableA
            case 1:
                dosomething();
                break;
            // TableB
            case 2:
                dosomething();
                break;
            // TableE
            case 5:
                dosomething();
                break;
            // 默认
            default:
                dosomething();
                break;
        }

 

这样,一切才真正OK了!!

(纯理论研究,没有测试。一切不良后果,概不负责!)

 

posted @ 2015-03-30 16:16  ↖(^o^)↗  阅读(335)  评论(0编辑  收藏  举报