1,任何为0的常量表达式都能隐式的转换成枚举Enum。
对于这一点,在程序中没少吃苦头。特别是对于函数重载的情况,往往让人一头雾水。
看看下面的代码(摘自MSDN),你能猜到输出吗?
public enum E { Zero = 0, One = 1, } class A { public A(string s, object o) { System.Console.WriteLine("{0} => A(object)", s); } public A(string s, E e) { System.Console.WriteLine("{0} => A(Enum E)", s); } } class B { static void Main() { A a1 = new A("0", 0); A a2 = new A("1", 1); A a3 = new A("(int) E.Zero", (int) E.Zero); A a4 = new A("(int) E.One", (int) E.One); } } Visual C# 2005 output: 0 => A(Enum E) 1 => A(object) (int) E.Zero => A(object) (int) E.One => A(object) Visual C# 2008 output: 0 => A(Enum E) 1 => A(object) (int) E.Zero => A(Enum E) (int) E.One => A(object)
自VS2008起,所有能确定为0的常量表达式都能隐式的转换成Enum。
所以如果不想要这种隐式的转换的话,在程序中处理0时,就需要转换。
再来看看我的测试例子:
namespace WZTEST { public partial class Form1 : Form { public Form1() { InitializeComponent(); } public void SqlParameter(string parameterName, object value) { //object } public void SqlParameter(string parameterName, SqlDbTypeA dbType) { //Enum } private void button1_Click(object sender, EventArgs e) { const int ZERO = 0; SqlParameter("aa", 0); SqlParameter("aa", (int)0); SqlParameter("aa", ZERO); SqlParameter("aa", Convert.ToInt32(0)); } } public enum SqlDbTypeA { Int = 1 } }
我们来反编译下button1_Click函数,看看编译器都做了什么。
private void button1_Click(object sender, EventArgs e) { this.SqlParameter("aa", (SqlDbTypeA) 0); this.SqlParameter("aa", (SqlDbTypeA) 0); this.SqlParameter("aa", (SqlDbTypeA) 0); this.SqlParameter("aa", Convert.ToInt32(0)); }
傻眼了吧!前面三个全部变成了Enum。好吧,既然斗不过微软,那就只有接受这个结果。
结论:对于有Enum的重载函数,传入0时,最好用Convert转换;或者用一个变量赋值0后再传入函数,以避开万恶的编译器规则。
备注:微软这样做的原因是Enum和0之间的比较比较频繁,为了方便开发者,就做了这样的隐式转换;但却给函数重载留下隐患,稍不小心就会犯错。