質問

次のコードを試してみました。

class Program: ProgParent
    {

        public int Max(params int[] op)
        {
            return 0;
        }

        public int Max(int i, params int[] op)
        {
            return 1;
        }

        public int Max(int i, int j, params int[] op)
        {
            return 2;
        }

        public static void Main(string[] args)
        {
            System.Console.WriteLine((new Program()).Max(5, 6, 7, 8));
            System.Console.ReadKey();
        }
    }

これが実行され、利用可能な最も具体的な関数が使用されます。しかし、コンパイラはこれに関して警告やエラーを出しません。なぜ?

役に立ちましたか?

解決

C# 言語仕様には次のように記載されています。

過負荷解像度を実行する場合、パラメーター配列を持つメソッドが通常の形式で適用される場合があります[IE配列を渡す]またはその拡張フォーム[すなわち可変数のパラメータを渡す]。メソッドの拡張形式は、メソッドの通常のフォームが使用できない場合にのみ使用でき、拡張されたフォームと同じ署名を持つメソッドが同じタイプで既に宣言されていない場合にのみ使用できます」

(少し簡略化して) 簡単に言うと、次のようになります。オーバーロードの解決があいまいな場合、コンパイラは非パラメータ オーバーロードを選択します。

(あなたのようなコードを違法にするのではなく)その決定の理由は次のとおりだと思います。

  • メソッドに署名がある場合:void fn(params object[] p) の場合、(object[] を渡すことによって)「通常形式」を呼び出す何らかの方法が必要です。したがって、コンパイラはとにかくあいまいなケースを処理する必要があります。
  • 一時配列の作成はメソッド呼び出しよりもはるかにコストがかかるため、動作は同じでより効率的な 1、2、3 パラメーターを持つ非パラメーター オーバーロードを作成することをお勧めします。(例えば文字列.形式)

他のヒント

(私はタイプミスまで入れている)ビルドエラーを無視する - どのような警告あなたが期待するかしたいですか?それはマッチングの過負荷を見つけ、それを使用している...

厳密に言えば、私は別のオーバーロードを呼び出すことができます - 。配列を渡すことで、しかし、はい、使用量は完全には明らかではありません。

params持つ複数のオーバーロードがなければ、このパターンはstring.Concatなど(ボンネットの下に文字列を+を支えている)のようなもので、かなり頻繁に使用されます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top