关于参数为可空值类型的多个重载的优先级 (彻底晕掉了)

最近使用ASP.NET MVC Preview 5做个小网站,发现一件很有趣的事情,里面不少地方有这种重载:XXX(string A, object B) 和 XXX(string A, string B),然后就发现了一个好玩儿的问题,再然后,突然冒出个想法,于是有了下面这些:

using System;
// 丁学, Ding Xue, http://www.cnblogs.com/dingxue
class Program
{
    static void Main(string[] args)
    {
        DingXue(null);
        Console.Read();
    }

    static void DingXue(Object p) { Console.WriteLine("Object"); }
    static void DingXue(String p) { Console.WriteLine("String"); }
}

你猜上面会调用哪个方法?基本上可以恭喜你,大部分人应该都可以猜出来结果是 String,那么下面这个呢?

using System;
// 丁学, Ding Xue, http://www.cnblogs.com/dingxue
class Program
{
    static void Main(string[] args)
    {
        DingXue(null);
        Console.Read();
    }

    static void DingXue(Object p) { Console.WriteLine("Object"); }
    static void DingXue(String p) { Console.WriteLine("String"); }
    static void DingXue(Int32? p) { Console.WriteLine("Int32"); }
}

再次恭喜,哈哈,报错了,String 和 Int32? 不明确,把String换成DateTime?,一样的错误,但是任意一个和Object一起都没有错误,而且都是调用 Object 之外的那个。嗯~~~,是不是只能是 Object 跟一个它派生出来的呢?看下面:

using System;
// 丁学, Ding Xue, http://www.cnblogs.com/dingxue
class Program
{
    static void Main(string[] args)
    {
        DingXue(null);
        Console.Read();
    }

    static void DingXue(Object p) { Console.WriteLine("Object"); }
    static void DingXue(Int16? p) { Console.WriteLine("Int16"); }
    static void DingXue(Int32? p) { Console.WriteLine("Int32"); }
    static void DingXue(Int64? p) { Console.WriteLine("Int64"); }
    static void DingXue(Single? p) { Console.WriteLine("Single"); }
    static void DingXue(Double? p) { Console.WriteLine("Double"); }
}

哇咔咔,居然全部和平共处,“优先级”依次是:Int16? -> Int32? -> Int64? -> Single? -> Double?,问题似乎明朗了起来,数字类型的似乎都可以共存,任意一个都可以与 Object 共存。

等等,好像还有一个是数字的,Decimal:

using System;
// 丁学, Ding Xue, http://www.cnblogs.com/dingxue
class Program
{
    static void Main(string[] args)
    {
        DingXue(null);
        Console.Read();
    }

    static void DingXue(Object p) { Console.WriteLine("Object"); }
    static void DingXue(Int16? p) { Console.WriteLine("Int16"); }
    static void DingXue(Int32? p) { Console.WriteLine("Int32"); }
    static void DingXue(Int64? p) { Console.WriteLine("Int64"); }
    static void DingXue(Decimal? p) { Console.WriteLine("Decimal"); }
}

嗯,果然验证了上面的结论,Decimal? 排在 Int64? 之后,呵呵,是不是发现有点不对劲?对了,Single? 和 Double? 不见了~~~~,那是因为~~它俩不能和 Decimal? 在一起,会“不明确”,汗~~~~~~~~

好了,最终结论:
1. 任意一个可为空的值类型都可以与 Object 共存,而不会被认为是错误的不明确的重载,但是 Object 永远不会被调用
2. String、DateTime等无法与其他非 Object 类型作为两个重载,会产生不能明确调用的错误
3. 整型(Int16/Int32/Int64)和浮点数(Single/Double)可以共存,优先级和大家想的一样,整型优先于浮点,小的优先于大的
4. 特殊的数字类型 Decimal 可以与整型共存,而优先级低于整型,但无法与浮点数共存

大家在写程序时应该很容易避免这种问题,但是既然MVC里出来了,那么就应该是有它的用处,那么,谁能告诉我这是为什么?

posted @ 2008-09-24 07:00  丁学  阅读(...)  评论(... 编辑 收藏