Code Fix

上級

does not contain a definition の原因と直し方(明示的インターフェース実装)

明示的インターフェース実装(void IWorker.Work()のような書き方)で定義したメンバーは、クラス型の変数からは見えません。インターフェース型の変数からしか呼び出せません。

エラーメッセージの読み方

Program.cs(8,11): error CS1061: 'Robot' does not contain a definition for 'Work' and no accessible extension method 'Work' accepting a first argument of type 'Robot' could be found (are you missing a using directive or an assembly reference?)
Program.cs
ファイル名
8
行番号
11
列番号 — この位置でコンパイラが解析に失敗しました
CS1061
エラーコード — 検索するとMicrosoftの解説ページが見つかります
'Robot' does not contain a definition for 'Work' and no accessible extension method 'Work' accepting a first argument of type 'Robot' could be found (are you missing a using directive or an assembly reference?)
内容 — 期待していたもの、または受け付けられなかったもの

このエラーが出る典型パターン

パターン1

 1  interface IWorker { void Work(); }
 2  class Robot : IWorker {
 3      void IWorker.Work() { System.Console.WriteLine("Working"); }
 4  }
 5  class Program {
 6      static void Main(string[] args) {
 7          Robot   r = new Robot();
               ^
 8          r.Work();
 9      }
10  }
Program.cs(8,11): error CS1061: 'Robot' does not contain a definition for 'Work' and no accessible extension method 'Work' accepting a first argument of type 'Robot' could be found (are you missing a using directive or an assembly reference?)

明示的インターフェース実装は、インターフェース型の変数からしか呼び出せません。クラス型の変数からは見えないメンバーになります。

直し方: Robot を IWorker にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  interface IFlyer { void Fly(); }
 2  class Bird : IFlyer {
 3      void IFlyer.Fly() { System.Console.WriteLine("Flying"); }
 4  }
 5  class Program {
 6      static void Main(string[] args) {
 7          Bird   b = new Bird();
               ^
 8          b.Fly();
 9      }
10  }
Program.cs(8,11): error CS1061: 'Bird' does not contain a definition for 'Fly' and no accessible extension method 'Fly' accepting a first argument of type 'Bird' could be found (are you missing a using directive or an assembly reference?)

BirdクラスにFlyメソッドが見えていても、それは明示的実装なのでBird型の変数からは呼び出せません。

直し方: Bird を IFlyer にします。

この問題を解いてみる →

パターン3

 1  interface IPrinter { void Print(); }
 2  class Report : IPrinter {
 3      void IPrinter.Print() { System.Console.WriteLine("Printing"); }
 4  }
 5  class Program {
 6      static void Main(string[] args) {
 7          Report   r = new Report();
                ^
 8          r.Print();
 9      }
10  }
Program.cs(8,11): error CS1061: 'Report' does not contain a definition for 'Print' and no accessible extension method 'Print' accepting a first argument of type 'Report' could be found (are you missing a using directive or an assembly reference?)

同じ理由で、Report型の変数からPrintは呼べません。複数のインターフェースで同名メソッドが衝突する場合によく使うテクニックです。

直し方: Report を IPrinter にします。

この問題を解いてみる →

パターン4

 1  interface ILogger { void Log(); }
 2  class Service : ILogger {
 3      void ILogger.Log() { System.Console.WriteLine("Logging"); }
 4  }
 5  class Program {
 6      static void Main(string[] args) {
 7          Service s = new Service();
               ^
 8          s.Log();
 9      }
10  }
Program.cs(8,11): error CS1061: 'Service' does not contain a definition for 'Log' and no accessible extension method 'Log' accepting a first argument of type 'Service' could be found (are you missing a using directive or an assembly reference?)

明示的インターフェース実装は、インターフェース型の変数からしか呼び出せません。

直し方: Service を ILogger にします。

この問題を解いてみる →

パターン5

 1  interface IValidator { void Validate(); }
 2  class Form : IValidator {
 3      void IValidator.Validate() { System.Console.WriteLine("Validating"); }
 4  }
 5  class Program {
 6      static void Main(string[] args) {
 7          Form       f = new Form();
                 ^
 8          f.Validate();
 9      }
10  }
Program.cs(8,11): error CS1061: 'Form' does not contain a definition for 'Validate' and no accessible extension method 'Validate' accepting a first argument of type 'Form' could be found (are you missing a using directive or an assembly reference?)

Form型の変数からはValidateが見えません。複数インターフェースの同名メンバーが衝突する場合によく使う手法です。

直し方: Form を IValidator にします。

この問題を解いてみる →

よくある誤解

同じクラスに定義されているのに「メンバーが見つからない」と言われるのは不自然に感じますが、明示的実装はそのインターフェース専用の実装だと明示するための機能です。

実務での勘所

明示的インターフェース実装が本当に役立つ場面は、1つのクラスが複数のインターフェースを実装していて、それぞれが同じ名前のメンバー(たとえばIWorker.Work()とIMachine.Work())を持っているが、意味は別物として実装したい場合です。通常の実装では1つのメンバーとして衝突してしまいますが、明示的実装を使えば、それぞれのインターフェース型として扱ったときだけ見える、別々の実装を1つのクラスに共存させられます。名前が衝突する複数のインターフェースを1つのクラスで実装する必要があるときの、専用の解決手段です。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)