[Effective C#] 項目13 static メンバは static コンストラクタで初期化する

本日の Effective C# は「項目13 static メンバは static コンストラクタで初期化する」です。

あれ?
[Effective C#] 項目12 割り当て演算子よりも変数初期化子を使用すること
では変数初期化子を使用するとか言ってたんじゃなかったのけ?

と思いました。

要はですね。

static 変数初期化子/static コンストラクタは CLR から呼び出され、例外が発生すると、即プログラムが停止するんだそうです。

それを避けるためには、static コンストラクタで変数の割り当てを行い、例外処理をきっちりしろということだそうな。

例外処理や複雑な処理が必要な場合は static 変数初期化子を使う方がよいとのこと。

静的変数初期化子および静的コンストラクタは、クラス内の静的メンバを初期化する最も明瞭な方法です。これらの方法を使うことで可読性が増し、エラーの修正も容易になります。C# 以外の言語において、静的メンバの扱いが複雑だったことを教訓として、言語機能に組み込まれました。

だそうです。

IEnumerator<T> と IEnumerable<T>

tag: 

.NET Framework には IEnumerator<(Of <(T>)>) インターフェイスIEnumerable<(Of <(T>)>) インターフェイスの二つを実装することで、イテレータパターンを実装することができます。


[Effective C#] 項目11 foreach ループを使用すること
にはさらっとしか書かなかったんですが。

[Effective C#] 項目12 割り当て演算子よりも変数初期化子を使用すること

本日の Effective C# は「項目12 割り当て演算子よりも変数初期化子を使用すること」です。

変数初期化子というのは、

[Effective C#] 項目11 foreach ループを使用すること

本日の Effective C# は、「項目11 foreach ループを使用すること」です。

まあ、言わずもがなな感じがします。でも、勉強ですからきちんと読んでみます。

ちなみに、プログラムを書くときに大事なことの一つに局所化があると思います。foreach を使うことが局所化と言えるかどうかは分かりませんが、while/for のループに比べると、要素を必ず一つずつ処理しているのが明確になるのが大事だと思います。

while/for を利用するということは、foreach を使えないロジックであることが明確になるのも大事です。

さて、概念的なことは置いておいて、Effective C# では、foreach を使用する理由は、安全性やパフォーマンスを挙げています。

[Effective C#] 項目10 GetHashCode() の罠に注意すること

本日の Effective C# は「項目10 GetHashCode() の罠に注意すること」です。

これですねぇ、私は大いなる間違いを犯しています。ここで懺悔しますから、許してください。

Object.GetHashCode メソッドはハッシュテーブルなどでの検索に使われます。線形サーチに比べると圧倒的に高速なのです。

もし独自に作成する型がコンテナのキーとして使用されることがないのであれば、この項目の話題は特に気にしなくてもかまいません。

うーん、一応、HashSet) クラスとかもあるので、キーのみってわけじゃないと思いますが、無理して実装する必要はないってことですね。

[Effective C#] 項目9 ReferenceEquals() と static メソッドの Equals()、インスタンスメソッドの Equals()、等号演算子 == の関係を把握する

本日の Effective C# は「項目9 ReferenceEquals() と static メソッドの Equals()、インスタンスメソッドの Equals()、等号演算子 == の関係を把握する」です。

長いよ…。

まずは等価・等値を調べるメソッド・演算子の一覧。

[Effective C#] 項目8 値型における 0 を正常な状態とすること

本日も眠いです…。

本日は「項目8 値型における 0 を正常な状態とすること」です。

列挙型において、0 を必ず指定すること、とあります。書籍に書いてある列挙型を引用します。

public enum Planet
{
    // 明示的に値を指定。そうでない場合は値0から増加
    Mercury = 1,
    Venus = 2,
    Earth = 3,
    Mars = 4,
    Jupiter = 5,
    Saturn = 6,
    Neptune = 7,
    Uranus = 8,
    Pluto = 9
}
 
Planet sphere = new Planet();

Pluto が Planet ですか…。あ、話が横道にそれた。(笑)

sphere は 0 に初期化されますが、その値は不正です。したがって、列挙型の取りうる値は定義済みの値に制限されるだろうという (一般的な) 事実を当てにしているコードにおいては、意図した挙動をとらないことになってしまいます。列挙型を定義する場合、常に 0 メンバとして定義すべきです。

拡張に対して開いていて、修正に対して閉じていること

tag: 

多分、ここ数年の間で一番感動した言葉がこれだと思う。オープン・クローズドの原則 (OCP)のことなんですが、「拡張に対して開いていて、修正に対して閉じていること」です。

プログラムをただ書くだけだと全然気がつかないんですが、これはとても大切なことです。

今までは、プロジェクトで書いたプログラムの場合、拡張しようとしたら、ソースコードを修正して対処してきました。拡張性があるということは、ソースコードが修正しやすいことだと思っていました。

ところが、修正して拡張する場合、switch 文などの分岐が増え、バグの温床になります。

例えばですが、Array.Sort() メソッドはこの原則に適合しています。

このメソッドを利用して、Customer インスタンスの配列をソートするとします。おそらくは、社員コード順に並ぶでしょう。では、名前でソートしたいと思ったら?

 

[Effective C#] 項目7 値型は不変かつアトミックにすること

今日のも長いなあ…。

本日の Effective C# は、「項目7 値型は不変かつアトミックにすること」です。

不変型といえば、一番有名なのは String 型でしょう。String オブジェクトはその値を一切変更することができません。値を変更できないのは不便かと思いきや、気にしたことがないくらいどうでもいいことでした。

不変型にすることで、以下の利点があると述べられています。

  • 多くの不要なエラーチェック処理を省略できる。
  • スレッドセーフである。
  • Object.GetHashCode() の実装が簡単

そして、アトミックかどうかは、関連性で見分ければいいようです。書籍では Address がアトミック、Customer はアトミックでないとしています。

同じく Address も Customer も複数の関連から成り立っていますが、Address は一つの要素で、Customer は複数の要素というのが理由だそうです。ちょっとチンプンカンプンだけど、言いたいことは分からないでもないかな。

Re: 壊してよいオモチャ(Breakable Toys)

tag: 

壊してよいオモチャ(Breakable Toys)
http://yshibata.blog.so-net.ne.jp/2010-03-01

自分も、この「ソフトウェアエンジニアの心得」の講義を受けたのですが…。

以下、日記から引用です。

「本のサンプルコードをやってみても上手く身に付かない」という質問がありました。

この質問した人すごいと思います。自分が努力していて、かつその努力の方向があっているのかどうか分からないというのが如実に分かります。また、"上手く身につかない" ことがわかっているのも素晴らしいと思います。こういう人はちょっとしたアドバイスでガンガン伸びると思います。

さて、柴田先生はそれに対し、壊してもいいオモチャ (Breakable Toys) を実践するのがよいと述べられています。では、なぜサンプルコードでは身につかないのでしょうかというお話をしたいと思います。

ページ

まさくらのブログ RSS を購読