この記事は機械翻訳のミラー記事です。元の記事にジャンプするにはこちらをクリックしてください。

眺める: 20516|答える: 0

[ヒント] C#プログラムを最適化する47の方法

[リンクをコピー]
掲載地 2018/03/15 10:41:59 | | |

1. アクセス可能なフィールドを属性に置き換える

1、. .NETのデータバインディングはデータバインディングのみをサポートしており、属性を使うことでその利点を得ることができます。
2. プロパティへのアクセスを取得・設定する際に、ロックを使ってマルチスレッドサポートを追加できます。

2. 読み取り専用(ランタイム定数)とコンセント(コンパイル時定数)

1. const はプリミティブ型、列挙式、文字列にのみ使用可能であり、readonly は任意の型に適用可能です。
2. コンセントはコンパイル時に特定の定数に置き換えられます。つまり、参照でコンスタントと読み取り専用の両方の值が使われている場合、読み取り専用に変更すると、変更されたアセンブリを再コンパイルして新しい定数値を参照する必要性が変わる設計の意図が変わります。
3. const は読み取り専用より効率的ですが、適用の柔軟性を失います。

3. ISとAS

1. どちらも実行時の型変換であり、演算子は参照型でのみ使用可能であり、 is は値と参照型を利用できます。
2. 通常の慣例は、型を決定するためにISを用い、その後選択的にまたは強い型変換演算子(オペレーターによって定義された変換)を選択的に使うことです。

4. 条件属性(ConditionalAttribute)を #if #endif条件编译

1. 条件属性はメソッドレベルでのみ使用され、型や属性などの他の項目は無効です。 そして #if #endif则不受此限制;
2. 条件属性はコンパイル条件に対して複数のOR(OR)演算を追加でき、#if #endif则可以添加与(AND)[ここでは別の別の記号として完全に定義可能です];
3. ConditioanlAttributeの定義は、プログラムをより柔軟にするために別のメソッドに配置できます。

5. ToString() メソッドを提供する

1. ユーザーに対してより親しみやすい方法で詳細な情報を提供できます。
2. IFormatter.ToString()メソッドを使ってより柔軟なカスタマイズを提供し、IFormatProviderとICustomFormatterのインターフェースを追加すれば、メッセージ出力のカスタマイズがより利意味を持ちます。

6. 値型と参照型の違い

1. 値型は多型を支持せず、アプリケーションが操作するデータの保存に適しています。一方、参照は多型性をサポートし、アプリケーションの動作定義に適しています。
2. 値型として定義された配列の場合、プログラムのパフォーマンスを大幅に向上させることができます。
3. 値型はヒープメモリ断片化、メモリのガベージ、間接アクセス時間が少なく、内部構造を外部に露出させないため、メソッドでの返還はレプリケーションの形で行われます。
4. 値型は以下のシナリオで使用されます:型の責任は主にデータ保存に用いられます。 公開インターフェースは、いくつかのデータメンバーアクセス属性によって完全に定義されます。 サブクラスは存在しません。 多型的な行動は決して存在しません。

7. 値型は可能な限り定数型かつ原子型で実装されるべきです

1. コードを書きやすく、保守しやすくすること;
2. 定数の初期化戦略:構成において; 植物法; 可変ヘルパークラス(例:StringBuilder)を構築します。

8. 0が有効なステータスに値することを確認すること

1. 値型のデフォルト状態は0であるべきです。
2. enum型の0は無効であってはならない; FlagsAttribute は 0 の値が有効な状態であることを保証するためです。
3. 文字列が空の場合、文字列を返すことができます。 空文字列は空文字列です。

9. 等しい判断の多重表現関係

1. ReferenceEquals() は参照が等しいことを判定し、両者が同じ対象を参照する場合に真である必要があります。
2. 静的Equals()法はまず参照判断を行い、その後値型を判断します。
3. 参照型の判断のために、値セマンティクスを使う際にRewrite Equals()メソッドを使用できます。
4. Equals() メソッドを書き換える際には、GetHashCode() メソッドも書き換え、同時にオペレーター==()演算も提供されるべきです。

10. GetHashCode() メソッドの欠点を理解する

1. GetHashCode() は、HashTableやDictionaryなどのハッシュベースの**定義キーのハッシュ値にのみ適用されます。
2. GetHashCode() は対応する3つのルールに従うべきです。すなわち、2つの等しいオブジェクトは同じハッシュコードを返すこと; はインスタンス不変であるべきです。 ハッシュ関数はすべての整数に対してランダムな分布を生成するはずです。

11. foreach loop文の使用を優先すること

1. foreachはforループの配列境界に対するコンパイラのチェックを省略できます。
2. foreachの循環変数は読み取り専用であり、明示的な変換が行われ、**オブジェクトのオブジェクト型が正しくない場合に例外が投げられます。
3. foreachを使用するために必要な**は次の通りです:公開のGetEnumberator()メソッドを持つこと; IEnumberableインターフェースは明示的に実装されています。 IEnumeratorインターフェースが実装されています。
4. foreachはリソース管理の利点をもたらします。なぜなら、コンパイラがIDisposableインターフェースを決定できれば、最適化されたtryを使えるからです... 最後にブロック;

12. デフォルトフィールドの初期化は割り当て文よりも優れている

1. フィールドライフはデフォルトで値型を0に、参照型をnullに初期化します。
2. 同じオブジェクトを複数回初期化すると、コードの実行効率が低下します。
3. フィールドの初期化をコンストラクタに配置することは例外処理に適しています。

13. 静的構造体を使って静的メンバーを初期化します

1. 静的構造体は、クラスのメソッド、変数、属性にアクセスする前に実行されます。
2. 静的フィールドは静的コンストラクタの前にも動作し、静的コンストラクタは例外処理に適しています。

14. コンストラクターチェーン(in . NET 4.0はオプションのパラメータでこの問題をすでに解決しています)

1. これを用いて初期化作業を別のコンストラクタに渡し、baseを使って基底クラスのコンストラクタを呼び出します。
2. 型インスタンスの操作列は次の通りです:すべての静的フィールドを0に設定; 静的フィールド初期化器の実行; ベースクラスを実行する静的コンストラクタ、 現在の型を実行する静的コンストラクタ;
すべてのインスタンスフィールドを0に設定します。 インスタンスフィールドの初期化器を実行してください; 適切なベースクラスインスタンス構造体を実行し、 現在のタイプのインスタンスコンストラクタを実行します。

15. 使用文とtry/final文を使ってリソースを整理する

IDisposableインターフェースのDispose()メソッドでは、GC.SuppressFinalize()を使って最終操作が終了したことをガベージコレクタに通知できます。

16. メモリのゴミを最小化する

1. ヒープ上のオブジェクトを割り当てて破棄するのに追加のプロセッサ時間が必要;
2. 割り当てられたオブジェクトの数を減らす手法:よく使われるローカル変数をフィールドに昇格させる; 特定の型を表現するシングルトンオブジェクトの一般的なインスタンスを格納するクラスを提供します。
3. StringBuilderを使って複雑な文字列操作を行う。

17. 荷造りと荷解きを最小限に抑える

1. 型がSystem.Objectに暗式的に変換されていることに注意し、値型はSystem.Object型に置き換えてはいけません。
2. 型の代わりにインターフェースを使うことで、ボックス化、つまりインターフェースから値型を実装し、メンバーをインターフェース経由で呼び出す方法を回避できます。

18. 標準処分モードの実装

1. 非メモリリソースを使用するには、フィニライザーが必要で、ガベージコレクタは実装されたフィニライザーオブジェクトを終了していないメモリオブジェクトを終了キューに追加し、その後これらのオブジェクトに対してフィニライザーを実行するために新しいスレッドを開始します。 これにより、管理されていないメモリリソースが解放されないことで生じるメモリリークの問題を回避できます。
2. IDisposable.Dispose() メソッドを使用するには、作業の4つの側面が必要です:すべての管理されていないリソースを解放すること; 管理されたすべてのリソースを解放し、 Dispose() が実行されたかどうかを示すステータスマーカーを設定する; GC.SuppressFinalize(this) を呼び出してオブジェクトの終了操作をキャンセルします。
3. 多型を必要とする型に保護された仮想メソッドDispose()を追加すると、派生クラスはこのメソッドを書き換えてタスクを解放します。
4. IDisoposableインターフェースを必要とするタイプでは、たとえ不要でもターミネーターを実装すべきです。

19. 継承型上のインターフェースを定義し実装する

1. 無関係な型は共通のインターフェースを共同で実装でき、継承よりもインターフェースの実装が容易である。
2. インターフェースは比較的安定しており、他の実装契約のように一連の関数をインターフェース内にカプセル化し、基底クラスは時間をかけて拡張可能です。

20. インターフェース実装と仮想メソッド書き換えを区別すること

1. ベースクラスでインターフェースを実装する際、派生クラスはベースクラスメソッドの使用を隠すためにnewを使う必要があります。
2. ベースクラスインターフェースのメソッドは仮想メソッドとして宣言され、派生クラスで実装されます。

21. 委任を用いてコールバックを表現する

1. デリゲート自体は例外キャプチャを提供しないため、マルチキャストデリゲートコールは通話チェーン全体を終了させます。
2. デリゲートチェーン上の各デリゲートターゲットを表示・呼び出すことで、マルチキャストのデリゲートが最後のデリゲートの出力だけを返すのを避けられます。

22. イベントを使って外部インターフェースを定義する

1. 共通イベントとして宣言し、コンパイラが加算・再移動メソッドを作成できるようにすべきです。
2. System.ComponentModel.EventHandlerListコンテナを使って各イベントハンドラーを格納し、型に多数のイベントが含まれている場合、すべてのイベントの複雑さを隠すために使います。

23. 内部クラスオブジェクトへの参照を返さないこと

1. 値型オブジェクトへのアクセスはそのオブジェクトのコピーを作成するため、値型を定義する属性は型オブジェクト内部の状態を一切変えません。
2. 定数型はオブジェクトの状態を変えずに済みます。
3. オブジェクトの内部状態への損傷を最小限に抑えるために、サブセットへのアクセスを制限するインターフェースを定義する。
4. 他のオブジェクトへのアクセスを制限するラッパーオブジェクトを定義する;
5. 顧客コードが内部データ要素を変更した場合、オブザーバーモードを実装し、オブジェクトがその変更を検証または対応できるようにします。

24. 宣言型プログラミングは命令型プログラミングよりも優れている

複数の類似した手書きアルゴリズムで誤りを犯す可能性を避け、明確で読みやすいコードが提供されます。

25. できるだけシリアライズ可能な型を実装する

1. 型はUIコントロール、ウィンドウ、フォームを表しず、型はシリアライズをサポートするべきです。
2. NonSerializedAttributeのdeserialized属性を追加する場合、デフォルト値はIDeserializationCallbackを実装するOnDeserialization()メソッドによって読み込めます。
3. バージョン管理では、柔軟な制御のためにISerializableインターフェースを使い、ストリーム内のデータに基づいてオブジェクトを初期化するためのシリアライゼーション構造体を提供し、実装時にSerializationFormatterの例外の許可も必要とします。
4. 派生クラスを作成する必要がある場合は、派生クラスに対してフックメソッドを提供する必要があります。

26. IComparableおよびIComparerインターフェースを使用してソート関係を実装する

1. IComparableインターフェースは、型の最も自然なソート関係を実装し、4つの比較演算子をオーバーロードし、特定の型をパラメータとして受け入れるためのCompareTo()メソッドのオーバーロード版を提供します。
2. IComparerは、IComparableとは異なるソート関係を提供するため、または型自体が実装されていないと示すソート関係を提供するために使われます。

27. IClonableインターフェースの回避

1. 値型については、ICloneableインターフェースをサポートする必要はなく、デフォルトの割り当て操作を使用すればよい。
2. IConeableインターフェースをサポートする必要があるベースクラスについては、保護されたレプリケーション構造体を作成し、IConeableインターフェースは避けるべきです。

28. 強制変換演算子の回避

コンストラクタを使うと変換がより明確になり、変換後に一時的なオブジェクトが使われて奇妙なバグが起きやすいです。

29. 新しい修飾子の使用は、新しいバージョンが蓄積されて問題が生じた場合のみ考慮してください

30. 可能な限りCLS互換アセンブリを実装する
1. 互換性のあるアセンブリを作成するためには、2つのルールに従う必要があります。アセンブリのすべての公開および保護メンバーが使用するパラメータおよび戻り値型はCLSと互換性があること、 CLSと互換性のない公開および保護されたメンバーは、CLS対応の代替を持たなければなりません。
2. インターフェースを明示的に実装することでCLSの互換性チェックを回避でき、CLSCompliantAttributeはプライベートメンバーのCLS互換性をチェックしません。

31. できるだけ短く簡潔な方法を実装する

1. JITコンパイラはメソッド単位でコンパイルし、呼び出されないメソッドはJITによってコンパイルされません。
2. 長いSwitchのCase文のコードを1つのメソッドに置き換えると、JITコンパイラで節約された時間が倍増します。
3. 短く簡潔な手法と局所変数の削減により、レジスタ利用の最適化が可能;
4. メソッド内の制御ブランチが少なければ少ないほど、JITコンパイラが変数をレジスタに配置しやすくなります。

32. できるだけ小型かつ高い凝集力を持つアセンブリを実現すること

1. すべてのパブリッククラスと共通基底クラスを一部のアセンブリに組み込み、パブリッククラスの関数を提供するツールクラスを同じアセンブリに組み込み、関連するパブリックインターフェースをそれぞれのアセンブリにパッケージ化し、最後にアプリケーション内の水平位置にあるクラスを処理する。
2. 原則として、2種類のコンポーネントを作成するべきです。1つは特定の機能を持つ小さく集約されたアセンブリ、もう1つは共通機能を持つ大規模で幅広いアセンブリです。

33. タイプの可視性を制限する

1. 型の関数を公開するためにインターフェースを使うことで、アセンブリ外での利用可能性を制限せずに内部クラスを簡単に作成できます。
2. 外部に露出するパブリックタイプが少なければ少ないほど、将来の拡張や変更の実装の選択肢が増えます。

34. 大規模で細かいWeb APIの作成

これにより、マシン間のトランザクションの頻度と負荷が最小化され、大規模な操作や細かい実行をサーバーに割り当てられます。

35. 書き換えはイベントプロセッサよりも優れている

1. イベントプロセッサが例外を投げた場合、イベントチェーン上の他のプロセッサは呼び出されませんが、書き換えられた仮想メソッドにはこの変更は起こりません。
2. 書き換えは、要求リスト全体を繰り返し処理する必要がある連想イベントプロセッサよりもはるかに効率的です。これによりCPU時間が増加します。
3. イベントは実行時により柔軟に応答でき、同じイベントに複数の応答を関連付けることができます。
4. 一般的なルールは派生イベントを扱うことであり、書き換えの方法がより適しています。

36. フェアユース。 .NET ランタイム診断

1. System.Diagnostics.Debug\Trace\EventLogは、プログラムがランタイムに診断情報を追加するために必要なすべてのツールを提供し、EventLogがその要素を提供したときにアプリケーションはシステムイベントログに書き込みできます。
2. 最後に、自分で診断ライブラリを書かないでください。.NET FCLにはすでに必要なコアライブラリがあります。

37. 標準的な構成機構を使用する

1、. .NETフレームワークのSystem.Windows.Applicationクラスは、共通の設定パスを確立するためのプロパティを定義しています。
2. Application.LocalAppDataPath と Application.userDataPath は、ローカルデータディレクトリおよびユーザーデータのパス名を生成します。
3. ProgramFilesやWindowsシステムディレクトリにはデータを書き込みません。これらの場所はより高いセキュリティ権限を必要とし、ユーザーが書き込み権限を持つことを期待しないでください。

38. データバインディングのカスタマイズとサポート

1. BindingMananger と CurrencyManager の2つのオブジェクトは、コントロールとデータソース間のデータ転送を実現します。
2. データバインディングの利点:データバインディングの使用は、自分でコードを書くよりもはるかに簡単です。 テキストデータ項目以外のスコープにも使用すべきです。他の表示プロパティもバインド可能です。 WindowOS Formsのデータバインディングでは、チェック関連データソースの複数の制御同期を処理できる機能、
3. オブジェクトが必要な属性をサポートしていない場合は、現在のオブジェクトをブロックしてから目的のオブジェクトを追加することでデータバインディングをサポートできます。

39. 使用。 .NET検証

1. ASP.NET には有効性を検証するための5つのコントロールがあり、CustomValidatorを使って新しいクラスを派生し、独自の認証器を追加できます。
2. Windowsの検証には、イベントハンドラを書くためにサブSystem.Windows.Forms.Control.Validating が必要です。

40. ニーズに応じて適切な**を選ぶ

1. 配列には2つの明らかな欠陥があります。動的にリサイズできないこと; サイズ変更は時間がかかります。
2. ArrayListは一次元配列と連結リストの特徴を組み合わせており、QueueとStackはArrayに基づく特別な配列です。
3. プログラムがアイテムの追加・削除に柔軟になれば、より堅牢な型を作れます。また、**をシミュレートするクラスを作成する際には、インデクサやIEnumberableインターフェースを実装すべきです。

41. DataSetはカスタム構造よりも優れています

1. DataSetには2つの欠点があります。XMLシリアライズ機構と non-.NET コードによるDataSet 間の相互作用があまり良くないこと、 DataSetは非常に多用途なコンテナです。
2. 強力なタイプのデータセットはより多くの設計ルールを破り、その開発効率は自ら書いたより洗練された設計よりもはるかに高い。

42. 特性を用いて反射を簡素化する

開発者に動的に利用可能な型、メソッド、属性を宣言させる特徴クラスを設計・実装することで、アプリケーションの実行エラーを減らし、ソフトウェアのユーザー満足度を向上させることができます。

43. 反射神経の使いすぎを避ける

1. Invokeメンバーが使用するパラメータと返り値はSystem.Objectで、実行時に型を変換しますが、問題が発生する可能性が高まっています。
2. インターフェースにより、より明確で保守しやすいシステムが得られ、反射は非常に強力な後期結合メカニズムです。 .NET FrameworkはWindowsコントロールやWebコントロールのデータバインディングを実装するためにこれを使います。

44. アプリケーション用の特定の例外クラスを作成する

1. 異なる例外クラスが必要な唯一の理由は、キャッチプロセッサを書く際にユーザーが異なるエラーに対して容易に異なるアプローチを取れるようにするためです。
2. 異なる修復動作がある場合、さまざまな例外クラスを作成し、例外ベースクラスでサポートされているすべての構造体を提供することで、アプリケーション用の完全に機能する例外クラスを作成し、InnerException属性を使って低レベルのエラー条件によって生成されるすべてのエラー情報を保存できます。

45. 異常な安全保証を優先すること

1. 強異常保証は例外からの回復と簡素化された例外処理の最良のバランスを提供し、例外によって操作が中断された場合でもプログラムの状態は変わりません。
2. 修正対象データの防御的コピーを行い、防御的コピーを修正します。途中の操作は例外を引き起こす可能性があり、一時的なコピーと元のオブジェクトが交換されます。
3. Terminator、Dispose()メソッド、Targetメソッドは、デリゲートにバインドされている場合、いかなる状況でも例外をスローしないようにしなければなりません。

46. 相互運用性の最小化

1. 相互運用性には3つのコストがあります。管理型ヒープと非管理型ヒープ間のデータ列挙コスト、マネージドコードと非マネージドコードの切り替えコスト、そしてハイブリッド環境を扱う開発者の開発コストです。
2. ブリッタブル型を相互運用で使用することで、オブジェクトの内部構造に影響されることなく、管理環境と非管理環境間を効果的に行き来できます。
3. In/Out機能を使って、最も適切で不要な複数レプリケーションを確保し、データの列挙方法を宣言することでパフォーマンスを向上させる。
4. COMコンポーネントとの相互運用性を最も簡単に実装するためにCOM Interoperを使用し、P/Invokeを使ってWin32 APIを呼び出し、またはC++コンパイラの/CLRスイッチを使ってマネージドコードと非マネージドコードを混用する;

47. 安全コードを優先する

1. 管理されていないメモリへのアクセスをできるだけ避け、孤立ストレージは管理コードや信頼できるユーザーへのアクセスを防げません。
2. アセンブリがウェブ上で動作する場合は、隔離ストレージの使用を検討し、特定のアルゴリズムがより高いセキュリティ権限を必要とする場合は、それらのコードを別のアセンブリで隔離すべきです。

48. 関連するツールとリソースを習得する

1. NUnitを使って自動ユニットテスト(VS2010に統合)を確立する;
2. FXCopツールはアセンブリ内のILコードを取得し、異種コーディングルールやベストプラクティスに照らして分析し、最終的に違反を報告します。
3. ILDasmはILの分解ツールで、詳細の洞察を得るのに役立ちます。
4. 共有ソースCLIは、.NETフレームワークのカーネルとC#コンパイラを含む実装のソースコードです。




先の:サービスファブリック - ステートフルサービスコンセプト
次に:詳細は.net/c# SynchronizationContextをご覧ください
免責事項:
Code Farmer Networkが発行するすべてのソフトウェア、プログラミング資料、記事は学習および研究目的のみを目的としています。 上記の内容は商業的または違法な目的で使用されてはならず、そうでなければ利用者はすべての結果を負うことになります。 このサイトの情報はインターネットからのものであり、著作権紛争はこのサイトとは関係ありません。 ダウンロード後24時間以内に上記の内容を完全にパソコンから削除してください。 もしこのプログラムを気に入ったら、正規のソフトウェアを支持し、登録を購入し、より良い本物のサービスを受けてください。 もし侵害があれば、メールでご連絡ください。

Mail To:help@itsvse.com