WebSurfer's Home

トップ > Blog 1   |   ログイン
APMLフィルター

Object 型と列挙型引数のオーバーロード

by WebSurfer 2013年8月10日 12:48

SqlParameterCollection.Add メソッド には以下のオーバーロードがあります。

  • Add (Object)
  • Add (SqlParameter)
  • Add (String, SqlDbType)
  • Add (String, Object)
  • Add (String, SqlDbType, Int32)
  • Add (String, SqlDbType, Int32, String)

このうち、Add(String, Object) は Add(String, SqlDbType) との曖昧さの問題で廃止され、代わりに AddWithValue メソッド の使用が推奨されています。

何が曖昧かと言うと、MSDN ライブラリの SqlParameterCollection.Add メソッド (String, Object) の説明に書いてありますように、第 2 引数に 0(整数ゼロ)を渡すと、Add (String, Object) ではなくて、Add (String, SqlDbType) オーバーロードが呼び出されることです。

第 2 引数に 0 を渡せばもちろん、(int)0 でも Add (String, SqlDbType) オーバーロードが呼び出されます。

Add (String, Object) オーバーロードを呼び出すには、第 2 引数に Convert.ToInt32(0) または (object)0 を渡さなければなりません。

何故でしょう? 以下のような理由だと思います。(多少推測があります)

まず、SqlDbType が列挙型というところが要注意です。MSDN ライブラリ Enumeration Types (C# Programming Guide) によると、0(整数ゼロ)は列挙型のデフォルト値とのことで、特別な意味を持つようです。

それゆえ、0 や (int)0 は SqlDbType 列挙型のデフォルト値と判断されるらしく、Add (String, Object) ではなくて、Add (string, SqlDbType) オーバーロードが呼ばれます。

Convert.ToInt32(0) は(Object 型から派生した)int 型、(object)0 は Object 型と判断されて、Add (String, Object) オーバーロードが呼ばれます。

ちなみに、もし Add (String, Int32) というオーバーロードがあったとすると、第 2 引数は 0 でも (int)0 でも Convert.ToInt32(0) でも、Add (String, Int32) オーバーロードが呼ばれるはずです。

検証するため以下のサンプルを作ってみましたが、サンプルコード内のコメントにあるように期待通りの結果となりました。

namespace MyConsoleApplication
{
    enum Days { Sat, Sun, Mon, Tue, Wed, Thu, Fri };

    class TestClass
    {
        public void Add1(object obj)
        {
            Console.WriteLine("Add1(object)");
        }

        public void Add1(Days d)
        {
            Console.WriteLine("Add1(Days)");
        }

        public void Add2(object obj)
        {
            Console.WriteLine("Add2(object)");
        }

        public void Add2(Days d)
        {
            Console.WriteLine("Add2(Days)");
        }

        public void Add2(int i)
        {
            Console.WriteLine("Add2(int)");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            TestClass tc = new TestClass();

            tc.Add1(0);
            tc.Add1(1);
            tc.Add1((int)0);
            tc.Add1(Convert.ToInt32(0));
            tc.Add1((object)0);

            Console.WriteLine("--------------------");

            tc.Add2(0);
            tc.Add2(1);
            tc.Add2((int)0);
            tc.Add2(Convert.ToInt32(0));
            tc.Add2((object)0);

            // 結果は:

            // Add1(Days)
            // Add1(object)
            // Add1(Days)
            // Add1(object)
            // Add1(object)
            // --------------------
            // Add2(int)
            // Add2(int)
            // Add2(int)
            // Add2(int)
            // Add2(object)
        }        
    }
}

Tags: ,

.NET Framework

About this blog

2010年5月にこのブログを立ち上げました。主に ASP.NET Web アプリ関係の記事です。

Calendar

<<  2024年3月  >>
252627282912
3456789
10111213141516
17181920212223
24252627282930
31123456

View posts in large calendar