大阪市中央区 システムソフトウェア開発会社

営業時間:平日09:15〜18:15
MENU

C#を使いこなせる気がしない。

著者:高木信尚
公開日:2018/09/22
最終更新日:2018/09/22
カテゴリー:技術情報

高木です。こんにちは。

私も完全におっさん化してしまって、新しいプログラミング言語やツールには全然ついていけません。
今回はそんな「ついていけない」プログラミング言語として、C#の話をしてみたいと思います。

以前にも、「C#難しすぎ」ということで、Disposeパターンが難しい&面倒すぎて、ストレスがたまっている話をしました。
Disposeパターンを使いこなせていないのは今も同じですが、やればやるほど自分の無力さを痛感するのがC#です。

そういえば、Javaもそんな感じでした。
それ以前に、Javaの理不尽さにすっかり嫌気がさして、極力関わり合いにはならないように忌避しています。
C#は、Javaほどの理不尽さはないものの、ちょっと本格的なものを作ろうとするとストレスMAXになってしまいます。

今悩んでいるのは、カプセル化がうまく実現できないことについてです。

たとえば、あるクラスがprivateな参照型のメンバーを持っているとします。
このメンバーを外部から参照したいのですが、安易にプロパティやメソッドで返してしまうと、参照型なのでオブジェクトの外で勝手にメンバーを破壊されてしまいます。

あるいは、クラスのメソッドの中にはオブジェクトの状態を変化させるメソッドもあればそうでないものもあります。
状態を変化させないメソッドは自由に呼んでもいいけれど、状態を変化させるメソッドの呼び出しを禁止したい状況があります。
そんな場合、C#では一体どう書けばいいのでしょうか?

一案としては、状態を変化させないプロパティやメソッドだけで構成されるインタフェースを用意して、それを実装する形でクラスを定義するというやり方があります。
ずいぶん面倒で回りくどいやり方ですが、確かにできないわけではなさそうです。

その場合でも、たとえば内部に保持する(配列などの)コレクションを参照させたいとき、コレクションそのものはリードオンリーで返すにしても、その要素は外からいくらでも破壊されてしまいます。
ReadOnlyCollectionなどを使う手もあるのは知っています。
しかし、その方法を使っても、要素に別のオブジェクトを代入されることは防げますが、要素が参照型であれば、そのオブジェクトを破壊されることまでは防げません。

今のところ、私に考えつく解決策は次の2点です。

  1. クラスの設計者とクライアントコードの設計者の間の紳士協定に委ねる。
  2. メンバーを外部から取得するときは、必ずディープコピーする。

どちらの方法もまったくイケてません。
1.のようなことをいうのであれば、C#のような中途半端な言語より、Cの精神を持つ言語のほうがずっと清々しいというものです。
2.はパフォーマンスが重要ではないならアリですが、あまり利口な方法だとも思えません。
それに、2.の方法を採用するにしても、オブジェクトの状態を変化させるメソッドの呼び出しは1.の紳士協定に依存するしかなくなります。

前回もそうでしたが、もしかすると私がC#の初級者だから、こんなつまらないことで躓いているだけかもしれません。
あるいは、おっさん化して頭が固くなったために、こんな簡単なこともできないのかもしれません。

最近はプログラミングのスクールの宣伝をよく見かけるので、私もそういうところに通って勉強したほうがよいのでしょうか?
あるいは、おっさんは素直にCやC++でも触っておいたほうがよいのでしょうか?
なかなか難しいところです。

  1. noname より:

    AsReadOnlyメソッドが使えるみたいですよ

    • 高木信尚 より:

      情報ありがとうございます。

      AsReadOnlyメソッドはReadOnlyCollectionとして返すものかと思います。
      本文中にも書きましたが、ReadOnlyCollectionでは要素への代入はできませんが、要素のプロパティへの書き込み等ができてしまいます。

上に戻る