does not implement interface member の原因と直し方
インターフェースを実装すると宣言したクラスが、そのメンバーの一部を実装していないときに出るコンパイルエラーです。
エラーメッセージの読み方
Program.cs(4,16): error CS0535: 'Person' does not implement interface member 'IGreeter.Greet()'
Program.cs- ファイル名
4- 行番号
16- 列番号 — この位置でコンパイラが解析に失敗しました
CS0535- エラーコード — 検索するとMicrosoftの解説ページが見つかります
'Person' does not implement interface member 'IGreeter.Greet()'- 内容 — 期待していたもの、または受け付けられなかったもの
このエラーが出る典型パターン
パターン1
1 interface IGreeter { 2 void Greet(); 3 } 4 class Person : IGreeter { 5 ^ 6 } 7 class Program { 8 static void Main(string[] args) { 9 Person p = new Person(); 10 p.Greet(); 11 } 12 }
インターフェースを実装すると宣言したクラスは、そのメンバーを全て実装する義務があります。1つでも欠けるとコンパイルエラーです。
直し方: (空) を public void Greet() { System.Console.WriteLine("Hi"); } にします。
パターン2
1 interface IShape { 2 double Area(); 3 } 4 class Square : IShape { 5 public double Side; 6 ^ 7 } 8 class Program { 9 static void Main(string[] args) { 10 Square s = new Square { Side = 2 }; 11 System.Console.WriteLine(s.Area()); 12 } 13 }
戻り値の型やアクセス修飾子もインターフェースの定義と一致させる必要があります。
直し方: (空) を public double Area() { return Side * Side; } にします。
パターン3
1 interface IDescribable { 2 string Describe(); 3 } 4 class Book : IDescribable { 5 public string Title; 6 ^ 7 } 8 class Program { 9 static void Main(string[] args) { 10 Book b = new Book { Title = "C#" }; 11 System.Console.WriteLine(b.Describe()); 12 } 13 }
publicを付け忘れるとアクセスレベルの不一致で同じCS0535になります。
直し方: (空) を public string Describe() { return Title; } にします。
パターン4
1 interface ICounter { 2 void Increment(); 3 } 4 class Tally : ICounter { 5 ^ 6 } 7 class Program { 8 static void Main(string[] args) { 9 Tally t = new Tally(); 10 t.Increment(); 11 } 12 }
インターフェースを実装すると宣言したクラスは、そのメンバーを全て実装する義務があります。
直し方: (空) を public void Increment() { System.Console.WriteLine("+1"); } にします。
パターン5
1 interface INamed { 2 string GetName(); 3 } 4 class Robot : INamed { 5 public string Label; 6 ^ 7 } 8 class Program { 9 static void Main(string[] args) { 10 Robot r = new Robot { Label = "R2" }; 11 System.Console.WriteLine(r.GetName()); 12 } 13 }
戻り値の型やアクセス修飾子もインターフェースの定義と一致させる必要があります。
直し方: (空) を public string GetName() { return Label; } にします。
よくある誤解
シグネチャ(戻り値の型・引数・アクセス修飾子)が1つでもインターフェースの定義と食い違うと、実装していないものとして扱われます。
実務での勘所
C# 8以降のインターフェースは、既定の実装(default interface method)を持つメンバーを定義できるようになりました。本体を持たない通常のインターフェースメンバーは実装が必須ですが、既定の実装が書かれているメンバーは、実装クラス側で省略してもコンパイルが通ります(インターフェース側の実装がそのまま使われます)。「インターフェースのメンバーは全部実装しなければならない」というルールは、C# 8以降は絶対ではなくなっています。