web-dev-qa-db-ja.com

C#可能なメソッド名がオプションのパラメーターと競合しています-なぜ禁止されていないのですか?

簡単なクラスとメインメソッドを作ってみましょう:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace Rextester
{
public class Program
{
    public static void Main(string[] args)
    {
       bar bar = new bar();
        bar.foo("a");
    }
}

public class bar
{
    public void foo(String a, String b = "b")
    {
        Console.WriteLine("Foo1");            
    }       

}
}

これは書きます

Foo1

コンソールに。

次に、オプションのパラメーターを使用して、メソッドのオーバーロードをクラスに追加します。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace Rextester
{
public class Program
{
    public static void Main(string[] args)
    {
       bar bar = new bar();
        bar.foo("a");
    }
}

public class bar
{
    public void foo(String a, String b = "b")
    {
        Console.WriteLine("Foo1");            
    }

     public void foo(String a)
    {
        Console.WriteLine("Foo2");            
    }


}
}

これは書きます

Foo2

コンソールに。

foo(String a、String b = "b")foo(String a)foo(文字列a、文字列b)シグニチャ、オプションのパラメータのため。しかし、私は間違っていました。なぜこれが許可されるのですか?

3
boucekv

Eric Lippertからの重要な 引用から始めるには

多くの人はこれを次のように考えているようです:

_void M(string x, bool y = false) { … whatever … }
_

これは実際には、これをC#で記述する必要があった方法の構文上の砂糖です。

_void M(string x) { M(x, false); }
void M(string x, bool y) { … whatever … }
_

そうではありません。ここでの構文糖は宣言側ではなく、呼び出し側にあります。方法は1つだけです。オプションの引数を省略して呼び出しを行うと、コンパイラーは呼び出しサイトに引数を挿入するだけです。あれは:

_M(“hello”);
_

として書き換えられます

_M(“hello”, false);
_

呼び出しサイトの書き換えとしてのC#のオプション引数の実装を本当に理解するには、シリーズ全体を読むことをお勧めします。基本的にあなたの期待

Foo(String a、String b = "b")はfoo(String a)とfoo(String a、String b)の両方の署名を表すと思います

それがどのように機能するかではありません。代わりに、foo(String a, String b = "b")は実際にはfoo(String a, String b)のみを表します。 Eric Lippertがあなたの直感が機能しない理由を提供する例として、foo(String a = "a", String b = "b")があると仮定します。この場合、foo(String)をうまく生成できません。

そのため、foo(String a, String b = "b")foo(String a)は、正当に同じクラスに属することができます(オプションのパラメーターは、宣言を変更するのではなく、呼び出し元に入力されるためです)。これはオプションのパラメーターの実装の自然な結果ですが、明らかにエラーが発生しやすいので、なぜそれが許可されないのかという疑問が依然としてあります。

私はここで決定的な答えはありませんが、実際にはC#の開発に関与している人しか言うことができませんが、Eric Lippertを別の言い方をすれば、言語のすべての機能に実装コストがあります。デザイナーが感じない機能は、実装しないだけのコストに見合う価値があります。この場合、おそらく正しくないコードを違法にすることは、明確なコストとわずかな利点しか持たない機能です(このようにオプションのパラメーターとオーバーライドを実際に混在させているのでしょうか?)。

3
walpen

メソッド呼び出しを作成すると、コンパイラーは、どのメソッドがどのパラメーターで呼び出されるかを判別します。 couldが呼び出されるすべてのメソッドをコンパイラーが決定するフェーズがあり、数値がゼロの場合はメッセージが表示され、複数ある場合は呼び出すのに最適なメソッドが決定されます。それが決定できない場合に不平を言う。

この場合、言語には、パラメーターが少ない関数を優先するルールがあります。個人的にはこれは良いルールだとは思いませんが、マイクロソフトは私の見解に同意しません。過負荷になりましたか

public func foo (String a, String c = "c")

警告があります。

1
gnasher729