C#:10の一般的な落とし穴とエラー

C#の「トラップ」 に関する記事の翻訳に注目してください。 この記事は、言語の複雑さにまだ慣れていないプログラマーを始めるのに役立ちます。



良い読書をしてください。






「これらはすべて些細なことです。些細なことです。 しかし、些細なことほど重要なことはありません。」



1.間違ったコレクションタイプを使用する



.Netには多くのコレクションクラスがあり、それらはすべて特定のタスクに特化しています。 クラスの選択は慎重に行う必要があります。 選択を間違えた場合、非効率的なコード、予期しない値を受け取り、コードの意味を理解できなくします。



詳細はこちら



2.利回りリターンを使用しない



呼び出されるオブジェクトをリストするときは、returnコレクションを作成するのではなく、yield returnステートメントを使用する必要があります( 翻訳者のメモ :状況によって異なります)。 このテンプレートの利点:





3.あいまいな日付の分析



あいまいな日付の分析に関しては、必ず形式を指定してください。 たとえば、「03/04/05」の行では、日、月、年が明確ではないため、ユーザーに重大なエラーが発生する可能性があります。



ここでは、 DateTime.ParseExact / DateTimeOffset.ParseExactを使用して、書式指定子を提供します。



var date = DateTime.ParseExact("01/12/2000", "MM/dd/yyyy", null)
      
      





4.インスタンスで例外を再処理する



例外をキャッチして再処理する場合は、必ず単純なスローを使用してください。 突然throw exを使用すると、例外呼び出しスタックが保存されません。



使用:



 catch(SomeException ex) { logger.log(ex); throw; }
      
      





使用しないでください:



 catch(SomeException ex) { logger.log(ex); throw ex; }
      
      





5.コンストラクター内の仮想コンポーネントへのアクセス



仮想記述子を使用すると、派生クラスでクラスメンバーをオーバーライドできます。 コンストラクターは、基本クラスから派生クラスまで実行されます。 つまり、基本クラスのコンストラクターからオーバーライドされたメソッドを呼び出すと、実行準備が整っていないコードが呼び出される可能性があります(これは、独自のコンストラクターでの初期化の完了に依存する場合があります)。



例:



 public class Parent { public Parent() { Console.WriteLine("Parent Ctor"); Method(); } public virtual void Method() { Console.WriteLine("Parent method"); } } public class Child : Parent { public Child() { Console.WriteLine("Child Ctor"); } public override void Method() { Console.WriteLine("Child method"); } }
      
      





子クラスの初期化は次のようになります。



  1. 親コンストラクター
  2. 子メソッド
  3. 子コンストラクター


つまり 子メソッドは、子コンストラクターの前に呼び出されます。



6.静的コンストラクターの例外



クラスが静的コンストラクターで例外をスローすると、クラスは役に立たなくなります。 非静的設計でさえ不可能です。 クラスは、参照されるたびに(静的または非静的に)System.TypeInitializationExceptionをスローします。



7.外部アセンブリのオプションのパラメーター



外部アセンブリから参照されている場合、オプションのパラメーターが期待どおりに機能しない場合があります。 DLLにいくつかの機能がパッケージ化されているとします。 そして、たとえば、コードに小さな変更を加えたい(オプションのパラメーターを別の値に変更したい)。



DLLのコンシューマーは、変更を有効にするために再コンパイルする必要があります。



詳細はこちら



8.非ユニバーサルオーバーロードを使用するユニバーサルメソッド



型Tのパラメーターと同じ名前の別のメソッドを使用するが、特定の型のパラメーターを使用するユニバーサルメソッドがあるとします。 コンパイラーは、パラメーターの各タイプにより適したメソッドを選択し、明示的に定義されたタイプは、汎用タイプよりも正確です。



たとえば、次のクラスがあります。



 class GenericTest { public void Test<T>(T parameter) { Console.WriteLine("Generic method!"); } public void Test(string parameter) { Console.WriteLine("Non-generic method!"); } }
      
      





そして、次のコード...



 var instance = new GenericTest(); instance.Test(7); instance.Test("foo");
      
      





結果が得られます:



 Generic method! Non-generic method!
      
      





つまり コンパイラは、2番目の呼び出しでより具体的な文字列メソッドを選択します。



9.辞書にオブジェクトを追加した後、ハッシュコードを変更します



辞書は、Object.GetHashCode()メソッドによって返されるキー値に依存します。 つまり、キーのハッシュコードは、辞書に追加された後は変更できません。



10.構造にリンクコンポーネントが含まれる場合、ValueType.Equalsは遅くなります



ValueType.Equalsを使用して2つのインスタンスを比較する場合は、構造に参照コンポーネントが含まれていないことを確認してください。 作業が遅いのは、ValueType.Equalsがリフレクションを使用して参照コンポーネントを定義するためであり、これは予想よりも少し遅い可能性があります。



原作者:ロバート・ベンツソン



All Articles