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がリフレクションを使用して参照コンポーネントを定義するためであり、これは予想よりも少し遅い可能性があります。

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

Source: https://habr.com/ru/post/J322394/


All Articles