6

ClassA次のように、別のクラスのコンストラクターを呼び出す 1 つのメソッドを含むクラス ( ) があるとします。

public class ClassA
{
    public void CallClassBConstructor()
    {
        using(ClassB myB = new ClassB()) {...}
    }
}

クラスClassBは次のようになります。

public class ClassB : IDisposable
{
    public ClassB(){}
    public ClassB(string myString){}
    public ClassB(ClassC myC){}
    public void Dispose() {...}
}

...そしてClassCさらに簡単です:

public class ClassC{}

これらのクラスを独自のアセンブリに配置し、ソリューション全体をコンパイルすると、エラーは発生しません。しかし、using ステートメントを次のように置き換えると:

using(ClassB myB = new ClassB("mystring")){...}

[mynamespace].ClassCinへの参照を追加するように求めるコンパイル エラーが表示されClassAます。私はまったく呼び出していないのでClassB(ClassC myC)、これは私には意味がありません.使用するかどうかに関係なく、他のコンストラクターのタイプを含める必要があるのはなぜですか? ClassCライセンス取得済みまたは入手困難なアセンブリに含まれていた場合はどうなりますか? これは、開発者が避けるべき悪い設計の例ですか、それともここに何かが欠けていますか?

4

3 に答える 3

9

ClassBコンストラクターを呼び出すときのメソッドのオーバーロードの解決に関係しています。

パラメーターなしでコンストラクターを呼び出すと、競合は発生しません。候補は1つしかないので、それが選ばれます。ClassAこの場合、参照する必要はありませんClassC

ただし、1 つのパラメーターでコンストラクターを呼び出すと、最初は両方の単一パラメーター コンストラクターが候補になります。この呼び出しを解決するために、コンパイラは について知る必要がありますClassC。ご存じのとおり、たとえばClassC、暗黙的な変換演算子を含めることができます。

(もちろん、この特定の例では、文字列を受け取る完全な一致があるため、そのような暗黙の変換演算子がとにかく起動しないことはわかっています — しかし、メソッドのオーバーロード解決ルールは、非常に明確に定義され、予測可能になるようにこのように定義されています。参照を追加すると、コードが別のコンストラクターのオーバーロードを突然呼び出す可能性があるように設計されていると想像してください。)

于 2010-09-02T11:47:12.017 に答える
1

コンストラクターのオーバーロードを解決するには、コンパイラーは関連する型を認識する必要があります。ClassCつまり、適切なコンストラクターのオーバーロードを選択するために知る必要がありますClassB

于 2010-09-02T11:45:30.817 に答える
1

これはClassC、別のアセンブリに配置したClassBが、コンストラクターの 1 つのパラメーターであるため、 のパブリック インターフェイスの一部であるためです。この型を含むアセンブリを参照する必要があります。参照しないと、コンパイラは型情報を解決する方法を認識できません。この特定のケースでは、コンパイラはすべてのコンストラクターのオーバーロードからすべてのパラメーターの型を解決して、正しいものを選択できるようにする必要がありますが、これはメンバーのオーバーロード自体の問題ではありません。これは、コンパイラが型情報を解決する必要があるときに発生します。戻り値の型でも発生する可能性があります。

于 2010-09-02T11:46:53.113 に答える