やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

C#チュートリアル(インタフェース)

 dotnet3.0上のC#8.0ではメンバを安全に追加できるらしいが、ドキュメントのコードがエラーになって確認できなかった。

成果物

情報源

 git cloneコマンドにてGitHubからリポジトリを取得しようとしたが、サイズが膨大すぎて断念した。1ファイルずつ生テキストを取得して手作業でファイル作成した。githubは一部のディレクトリ配下だけ取得することができないため、こういうクソ面倒なことになるのが嫌。

プロジェクト作成

dotnet new console -o Tutorial_Interface
cd Tutorial_Interface

コード

 シナリオの概要の項までならドキュメントどおりに作れる。

 次の既定のインターフェイス メソッドを使用してアップグレードするの項からはGitHubからコードを取得する必要がある。SampleCustomerクラスなどドキュメントに書いていないのに突如登場するから。

ドキュメントのコードはコンパイルエラーになる

 ドキュメントには以下のメソッドを追加しろとある。

ICustomer.cs

// Version 1:
public decimal ComputeLoyaltyDiscount()
{
    DateTime TwoYearsAgo = DateTime.Now.AddYears(-2);
    if ((DateJoined < TwoYearsAgo) && (PreviousOrders.Count() > 10))
    {
        return 0.10m;
    }
    return 0;
}

 だが、これを実行するとエラーになる。

Lesson1/ICustomer.cs(19,63): error CS1061: 'IEnumerable<IOrder>''Count' の定義が含まれておらず、型 'IEnumerable<IOrder>' の最初の引数を受け付けるアクセス可能な拡張メソッド 'Count' が見つかりませんでした。using ディレクティブまたはアセンブリ参照が不足していないことを確認してください。 [/tmp/work/Tutorial_Interface/Tutorial_Interface.csproj]

 MSDNにはCountメソッドが存在する。ただ、source型がIColectionを実装している場合とある。エラーになった上記コードでのsource型はIOrder型である。これは特に継承など何も指示していないインタフェースなのでICollection<T>を実装していないはず。だからエラーになったのだろう。

 さらにドキュメントに書いてある当該コードは、GitHubには書いてない。つまりドキュメントはコンパイルエラーになる虚偽コードを載せていたことになる。それをもとにC#8.0インタフェースの新機能について説明している……。それでは何も確認できない……。

 しかもそれが完了した前提で話を進めてなかなかのスタートですとか書いてあるから最高にイラつく。その前に提示されたコードがコンパイルエラーになるんですけど? これ以上の学習が進められないんですけど? 何もスタートしないんですけど?

 ドキュメントの最後の項GitHubにコードがあるかのように書かれているが、やはりドキュメントにかかれているコードはGitHub上のコードに書いていない。

GitHub 上の サンプル リポジトリで完成したコード全体を確認できます。 GitHub 上の サンプル リポジトリでスターター アプリケーションを入手できます。

 このページの次ページには以下もあるというのに……。

所感

メソッドを安全に追加する

 結局、C#8.0の新機能とやらが何なのかよくわからなかった。メソッドを安全に追加できるって、どういう意味なの?

 最後の項を読むかぎり、インタフェース側にprotected staticで処理内容を実装してそれをインタフェースメソッドで呼出するようにしてある。そのインタフェースを継承した側で、インタフェースメソッドをオーバーライドすれば、インタフェース側のprotected static処理が無視されて新しく独自実装できるっぽい。

インタフェースにメンバ変数やメソッドを追加できるようになった

 protected staticなメソッドを追加できるようになったのも、この仕様変更のおかげっぽい。

 これまでインタフェースは実装のないメソッドシグニチャのみ追加できた。実装のあるメソッドやメンバ変数は追加できない仕様だった。それらは抽象クラスを用いることで実現していたはず。だがdontnet3.0上のC#8.0では、それらがインタフェースで実装できるようになったらしい。

次回

 これをヒントに、動作するコードを自分で書いてみよう。

対象環境

$ uname -a
Linux raspberrypi 4.19.42-v7+ #1218 SMP Tue May 14 00:48:17 BST 2019 armv7l GNU/Linux