web-dev-qa-db-ja.com

内部実装を備えたC#内部インターフェイス

よくわからないことがありました。

プロジェクトがあり、内部のインターフェイスがあります。そのインターフェイスを実装するクラスも内部です。インターフェースの実装では、実装するすべてのメンバーを内部にします。明示的な実装は行いませんでした。

2つのインターフェイスと、これらが正常に機能するインターフェイスを実装する2つのクラスがあります。

次のようになります。

internal interface IA
{
    void X();
}

その後

internal class CA : IA
{
    internal void X()
    {
        ...
    }
}

これは、前述の2つのクラスで正常に機能します。しかし、別のインターフェイスとクラスでそれを行おうとすると、うまくいきません。実際、上記の例では、エラーが発生します。

「WindowsFormsApplication1.CA」は、インターフェイスメンバ「WindowsFormsApplication1.IA.X()」を実装しません。 'WindowsFormsApplication1.CA.X()'は、パブリックではないため、インターフェイスメンバを実装できません。

メソッドをパブリックにするか、明示的な実装を行うことができます(内部修飾子とパブリック修飾子を省略します)が、それが動作する2つのクラスで動作する理由について単純に混乱していますが、複製することはできないようですそれはどこでも。

コードを少し肉体化する(機密であるため)が、これは私のプロジェクトで実際に機能するものの1つです。

internal interface IScanner
{
    void SetHardware(Hardware hardware);
    void Start();
    void PauseScan();
    void ResumeScan();
    void Stop();
    bool InScan { get; }
    event ScanCompleteHandler ScanComplete;
}

次に、クラスがあります:

internal class MyScanner : IScanner
{
    internal void SetHardware(Hardware hardware)
    {
       ...
    }

    internal void Start()
    {
        ...
    }

    internal void Stop()
    {
        ...
    }

    internal void PauseScan()
    {
        ...
    }

    internal void ResumeScan()
    {
        ...
    }

    internal bool InScan
    {
        get
        {
            ...
        }
    }

    internal event ScanCompleteHandler ScanComplete;
}

物事をさらに奇妙にするために、Tempという別の内部クラスを作成しました。次に、IScannerインターフェイスを実装し、MyScannerから実装をコピーして貼り付けましたが、コンパイルされず、「パブリックではないためインターフェイスメンバを実装できません」というエラーが表示されました。

誰でもこの矛盾を説明できますか?

ありがとう

(タイプミスを修正し、テキストを明確にするために更新されました)

編集:追加情報

リフレクターを介してコードを実行し、明示的ではありませんが、実装は明示的実装としてコンパイルされています。 Reflectorは内部キーワードの兆候を示しません。私が推測できるのは、これが何らかの理由でコンパイラを内部的かつ暗黙的にすることを許可したコンパイラの不具合であり、それを何らかの形で明示的な実装として解決したことです。

私は何度もコードを見てきました。他の説明は見つかりません。

42
Pete

この質問が出されてからしばらく経ちましたが、おそらく少し光を当てることができます。見つかったC#言語仕様によると、 here 記述した動作は不可能です。 20.4.2インターフェースマッピングでは、実装は明示的であるか、public非静的メンバーにマッピングされると言われているためです。したがって、ここで説明しているシナリオ以外のシナリオがあるか、コンパイラでバグを見つけました:)。

3
S. Larws

インターフェース宣言に内部修飾子を含めることはできますが、インターフェース内に修飾子を含めることはできません。つまり、インターフェースメンバーに修飾子を付けることはできません。それは簡単です!

例:

internal interface IA
{
    void X(); //OK. It will work
}


internal class CA : IA
{
    **internal** void X() // internal modifier is NOT allowed on any Interface members. It doesn't compile. If it works in your project it's because either you DON'T have the void X() method in the Interface or your are inheriting from a wrong interface maybe accidentally 
    {
        ...
    }
}

インターフェイス宣言では、ゼロ個以上のメンバーを宣言できます。インターフェイスのメンバーは、メソッド、プロパティ、イベント、またはインデクサーでなければなりません。インターフェイスに定数、フィールド、演算子、インスタンスコンストラクタ、デストラクタ、または型を含めることはできません。また、インターフェイスにあらゆる種類の静的メンバーを含めることはできません。すべてのインターフェイスメンバーは暗黙的にパブリックアクセスを持ちます。インターフェイスメンバー宣言に修飾子を含めると、コンパイル時エラーになります。特に、インターフェイスメンバは、修飾子abstract、public、protected、internal、private、virtual、override、またはstaticで宣言できません。

リファレンス: https://docs.Microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/interfaces

2
Rick

おそらく、「Temp」クラスはパブリックであり、IScannerは内部にあります。これがこのエラーを受け取る理由です。あなたはそれを明示的に実装することを余儀なくされているため、抽象的または仮想として指定することはできないため、これは非常に迷惑です。仮想的なものについては、同じAPIの暗黙的な内部仮想実装を実行し、明示的なバージョンから暗黙的なバージョンを呼び出すことを余儀なくされました。醜い。

2

私の知る限り、インターフェイスメソッドinternalを実装することはできません。あなたが述べたように、それらを明示的に実装することはできますが、だれかが_((IScanner)myScanner).SetHardware(hw)

MyScanner実装がこのようなことをしないことを100%確信していますか:

internal class MyScanner : IScanner
{
    void IScanner.SetHardware(Hardware hardware) { this.SetHardware(hardware); }
    internal void SetHardware(Hardware hardware)
    {
      ...
    }
    ....
}

またはこれ:

internal partial class MyScanner : IScanner
{
    internal void SetHardware(Hardware hardware)
    {
        ...
    }
}

internal partial class MyScanner
{
    void IScanner.SetHardware(Hardware hardware)
    {
        this.SetHardware(hardware);
    }
}
0
ChrisWue