!!!Effective C# 4.0 [C#][Visual Studio][言語まとめ C#] {{amazon 4798122513}} !!イディオム !アクセス可能なデータメンバの代わりに常にプロパティを使用すること *.NET Frameworkは、データメンバーを公開する場合、プロパティとして公開されることを前提としています *プロパティはメソッドとしての言語機能をすべて備えるため、virtualキーワードを指定することも出来る *プロパティの自動実装構文が言語によりサポートされる **バッキングストアと呼ばれるprivateメンバ変数、アクセッサーをコンパイラが自動実装 public class Foo { public string Name { get; set; } } *プロパティの自動実装構文と同じ構文を使用して、抽象クラスやインターフェースのメンバープロパティを実装出来る public interface IHoge { T Value { get; set; } } ""型が持つデータをpublicまたはprotectedとして公開する場合、常にプロパティを使用するべき。一連のデータやディクショナリを含む場合、インデクサを定義する。 !constよりもreadonlyを利用する // コンパイル時定数 public const int Millennium = 2000; // 実行時定数 public static readonly int ThisYear = 2014; *コンパイル時定数はメソッド中で定義することも出来るが、実行時定数はできない。 *コンパイル時定数は、コンパイル時にリテラル値に置き換えられる。 *コンパイル時定数はプリミティブ型の中で、コンパイル時にリテラルに置き換えられる物のみ指定できる。 // コンパイル時定数指定不可 public static DateTime BirthDay = new DateTime(1971, 9, 30); ""コンパイル時に値が決まっていなければならない場合は、const利用必須だが、まれなケース。リリースを重ねても値が不変である必要がある。そうでなければ、readonly を利用し、柔軟な処理を行えるようにすべき !キャスト時にはisあるいはas演算子を使用すること *ダウンキャストには2つの方法がある **as演算子を利用する **C言語以来のキャストを利用する *できる限りasを利用するのが最良の選択 ""as 演算子はキャスト操作とよく似ています。 ただし、変換可能でない場合、as は、例外は発生せず、null を返します。 object o = GetObject(); Base b = o as Base; if (b != null) { // 変換したオブジェクトを利用する } else { // 変換出来ない } !#ifの代わりにConditional属性を使用する *#if/#endifを多用するとソースが読みにくくデバッグしにくくなる *Conditional属性が付与されたメソッドは、環境設定のにしたがって実行の有無が切り替えられる public void Test() { CheckState(); } [Conditional("DEBUG")] public void CheckState() { Console.Write("Now Debugging."); } *Conditional属性によって生成される中間言語は、#if/#endifで生成されるものより効率的 *メソッド単位でのみ指定可能という制限のため、条件により実行可否を変えるコードを明確に分離出来る !ToString()を常に実装すること *複雑な情報を持つ型を作成する場合には、IFormattable.ToString() を実装し、書式が指定された文字列表現を取得できるようにする。 *型固有の情報を返すToString()メソッドを実装することで、開発者、使用者の時間の節約になる。 *C#3.0以降では、コンパイラがすべての匿名型に対し、デフォルトのToString()メソッドを作成する。 var test = new {Name="Me"}; Console.WriteLine(test); ::結果 { Name = Me } !さまざまな同値性メソッドの関係を把握する !GetHashCodeの罠に注意する !ループの代わりにクエリ構文を使用すること !独自のAPIでは変換演算子を定義しないこと !メソッドのオーバーロードを最小限にするよう、オプション引数を使用する !機能を最小限かつシンプルにすること !!リソース管理 !割り当て演算子よりもメンバ初期化子を使用すること !staticメンバは適切に初期化する !初期化ロジックの重複を最小化する !using および try...finally を使用してリソースの後処理を行う !不必要なオブジェクトの生成を避けること !Disposeパターンの標準的な実装 !値型と参照型の違い !値型における0を正常な状態にすること !値型は不変かつアトミックにすること !!デザインの表現 !型の可視性を制限すること !継承よりもインターフェースの定義および実装を行うこと !インターフェースメソッドと仮想メソッドの違いを理解する !デリゲートを利用してコールバックを実現する *デリゲートはタイプセーフなコールバックを定義します。 *デリゲートの最も一般的な用途はイベントと組み合わせる方法だが、それだけに限らない *互いのクラス間でデータをやり取りする必要があるが、互いのインターフェースを使用するほどには密に連携させたくない場合最善の選択肢 *対象を実行時に決定でき、複数の相手に同時に通知できる ""デリゲートとはメソッドへの参照を含んだオブジェクト *C#にはデリゲートを表現するためのラムダ式形式の構文が用意されている *Predicate,Action<>,Func<> など一般的なデリゲート形式が数多く用意されている !イベントパターンの実装により通知を行うこと !クラス内オブジェクトの参照を返さないようにすること !型はできるだけ、シリアル化可能にすること !粒度の粗いインターネットサービスAPIを作成する !ジェネリックの共変性と反変性をサポートする !!フレームワークの活用 !イベントハンドラよりもオーバーライドを優先すること !IComparableとICompareを実装して順序関係をサポートする !ICloneableを使用しないこと !親クラスの変更に応じる場合のみnew修飾子を使用すること !基本クラスに定義されたメソッドをオーバーロードしないこと !PLINQが並列アルゴリズムを実装する方法 !I/Oのコストが高い処理に対して、PLINQを使用する方法 !例外を考慮した並列アルゴリズムを構成すること !!動的プログラミング !dynamic の利点と欠点を把握する !ジェネリック型引数の実行時型を活用するためにdynamicを使用する !匿名型を引数にとれるようdynamicを使用する !DynamicObjectあるいはIDynamicMetaObjectProvidorを使用してデータ駆動のdynamic型を作成する !Expression APIを活用する方法を把握する !式を使用して事前バインディングを遅延バインディングに切り替える !公開するAPIでは動的オブジェクトを最小限に抑えること !!その他 !ボックス化、ボックス化解除を最小限に抑える !完全にアプリケーション固有の例外クラスを作成する !例外を強く保証すること !安全なコードを採用すること !CLS互換性のあるアセンブリを作成すること !より小さく凝集したアセンブリを作成すること