web-dev-qa-db-ja.com

コンパイルエラー:明示的にインターフェイスを実装しているときに、「修飾子 'public'はこのアイテムに対して無効です」

publicを明示的に実装するクラスでinterfaceメソッドを作成しているときにこのエラーが発生します。回避策があります:PrintNameメソッドの明示的な実装を削除することにより。しかし、なぜこのエラーが発生するのか、驚きました。

誰でもエラーを説明できますか?

ライブラリのコード:

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

namespace Test.Lib1
{

    public class Customer : i1 
    {
        public string i1.PrintName() //Error Here...
        {
            return this.GetType().Name + " called from interface i1";
        }
    }

    public interface i1
    {
        string PrintName();
    }

    interface i2
    {
        string PrintName();
    }
}

コンソールテストアプリケーションのコード:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Test.Lib1;

namespace ca1.Test
{
    class Program
    {
        static void Main(string[] args)
        {
            Customer customer = new Customer();
            Console.WriteLine(customer.PrintName());

            //i1 i1o = new Customer();
            //Console.WriteLine(i1o.printname());

            //i2 i2o = new Customer();
            //Console.WriteLine(i2o.printname());

        }
    }
}
57
Lalit

explicitインターフェースの実装を使用すると、メンバーはクラス自体でprivateよりも制限されたものに強制されます。また、アクセス修飾子が強制されている場合、追加することはできません。

同様に、インターフェース自体では、すべてのメンバーはpublicです。インターフェイス内に修飾子を追加しようとすると、同様のエラーが発生します。

明示的なメンバーが(非常に)プライベートなのはなぜですか?考慮してください:

_interface I1 { void M(); }
interface I2 { void M(); }

class C : I1, I2
{
    void I1.M() { ... }
    void I2.M() { ... }
}

C c = new C();
c.M();         // Error, otherwise: which one?
(c as I1).M(); // Ok, no ambiguity. 
_

これらのメソッドがパブリックである場合、通常のオーバーロードルールでは解決できない名前の衝突が発生します。

同じ理由で、_class C_メンバー内からM()を呼び出すことさえできません。同じ曖昧さを避けるために、最初にthisを特定のインターフェースにキャストする必要があります。

_class C : I1, I2
{
   ...
   void X() 
   {  
     M();             // error, which one? 
     ((I1)this).M();  // OK 
   }
}
_
71
Henk Holterman

http://msdn.Microsoft.com/en-us/library/aa288461(VS.71).aspx :メンバーが明示的に実装されている場合、メンバーはクラスインスタンスを介してアクセスできませんが、インターフェイスのインスタンスを介して。

_Customer customer = new Customer();
_

Console.WriteLine(customer.PrintName());

これに違反する

11
hackerhasid

インターフェイスを明示的に実装する場合、アクセス修飾子を使用できません。いずれにせよ、メンバーはインターフェイスにバインドされるため、すべてのインターフェイスメンバーは常にパブリックであるため、アクセス修飾子を指定する必要はありません。また、明示的に実装されたすべてのメンバーは、インターフェイスタイプのメンバーを通じてのみアクセスできます(statichippoの回答を参照)。

7
Andrew Bezzub