6

.NETの例を示します。

ConcurrentDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IDictionary

ここでは、ConcurrentDictionaryが辞書インターフェースを実装しているのを見ることができます。Add<TKey,TValue>ただし、ConcurrentDictionaryインスタンスからメソッドにアクセスできません。これはどのように可能ですか?

IDictionary<int, int> dictionary = new ConcurrentDictionary<int, int>();
dictionary.Add(3, 3); //no errors

ConcurrentDictionary<int, int> concurrentDictionary = new ConcurrentDictionary<int, int>();
concurrentDictionary.Add(3, 3); //Cannot access private method here

アップデート:

アクセス方法は知っていますが、インターフェイスを明示的に実装すると、アクセス修飾子を内部に変更できることを知りませんでした。ただし、それでもプライベートにすることはできません。これは正しいです?その部分についてのより詳細な説明が役立つでしょう。また、いくつかの有効なユースケースを教えてください。

4

7 に答える 7

7

IDictionary.AddメソッドはConcurrentDictionaryによって明示的に実装されているためです。

変数をIDictionaryとして宣言せずにクラスからアクセスするには、必要なインターフェイスにキャストします。

((IDictionary)concurrentDictionary).Add(3, 3)
于 2013-01-11T14:32:15.310 に答える
5

これは、明示的なインターフェイスの実装を通じて行われます

public interface ISomeInterface
{
    void SomeMethod();
}

public class SomeClass : ISomeInterface
{
    void SomeInterface.SomeMethod()
    {
        // ...
    }
}

これで、オブジェクトへの参照がある場合、使用可能なメソッドSomeClassは表示されませSomeMethodん。それを呼び出すには、オブジェクトをキャストして戻す必要がありISomeInterfaceます...

((ISomeInterface)mySomeClass).SomeMethod();

これは、C#imoの十分に活用されていない便利な機能の1つです。

于 2013-01-11T14:32:02.600 に答える
4

これは明示的なインターフェースIDictionary<TKey, TValue>実装として実装されています。つまり、アクセスするにはタイプの変数が必要です。

のドキュメントのConcurrentDictionary<TKey, TValue>「明示的なインターフェイスの実装」セクションを参照してください。

並行辞書をにキャストすると、それIDictionary<TKey, TValue>を呼び出すことができますAdd


インターフェイスを明示的に実装すると、アクセス修飾子をinternalに変更できることを知りませんでした。ただし、それでもプライベートにすることはできません。これは正しいです?

いいえ、これは正しくありません。

明示的なインターフェースの実装は、アクセス修飾子を変更しません。それらは、そのように実装されたメンバーにアクセスする方法を変更します(つまり、インターフェースタイプの変数を使用する必要があります)。これらは引き続きパブリックメンバーですが、実装タイプではなく、インターフェイスタイプを使用してのみアクセスできます。

于 2013-01-11T14:32:24.313 に答える
2

明示的なインターフェースの実装。より簡単な例:

public interface IFoo {
    void Bar();
}
public class Foo : IFoo {
    void IFoo.Bar() { ... }
}

ここBarはのパブリックAPIではありませんFoo

于 2013-01-11T14:32:46.637 に答える
2

インターフェイスは明示的に実装されます。Add次の例では、Aクラスのインスタンスを使用してメソッドにアクセスすることはできません。

public interface IA
{
    void Add();
}

public class A : IA
{
    void IA.Add()
    {
        throw new NotImplementedException();
    }
}
于 2013-01-11T14:37:11.027 に答える
0

アクセス修飾子は変更されていません。ConcurrentDictionary<TKey, TValue>明示的なインターフェイスの実装を通じてメソッドを定義しましたが、メソッドIDictionary.Addを実装していませんAdd

クラスのドキュメントを見ると、Addメソッドが存在しないことがわかります(したがって、のconcurrentDictionary.Add(3, 3);呼び出しに類似していますconcurrentDictionary.MethodThatDoesntExist(3, 3);)。ただし、[明示的なインターフェイスの実装]セクションICollection.Addでは、メソッドとが存在することがわかりますIDictionary.Add

この機能により、クラスは、実装が各インターフェースで同じである必要なしに、メソッド名を共有する複数のインターフェースを実装できます。

于 2013-01-11T15:00:12.100 に答える
0

すばらしい回答をありがとうございました。削除された回答の1つで、アクセス修飾子について混乱しました。リンクされた質問からいくつかの素晴らしい説明を見つけることができました。

MichaelHopcroftによる暗黙的および明示的なインターフェイスの実装

JonSkeetによるいくつかのユースケース

IDisposableを明示的に実装する

BradAbramsによる明示的なメンバー実装の設計ガイドライン

厄介なあいまいなオーバーロード、パート1パート2、Eric Lippert

于 2013-01-11T15:22:21.177 に答える