遅延初期化を使用することに決めた場合、通常はその代償を払わなければなりません。
class Loafer
{
private VeryExpensiveField field;
private VeryExpensiveField LazyInitField()
{
field = new VeryExpensiveField();
// I wanna here remove null check from accessor, but how?
return field;
}
property Field { get { return field ?? LazyInitField(); } }
}
基本的に、バッキング フィールドに null/nil 値があるかどうかを毎回確認する必要があります。彼がこの習慣から逃れることができたらどうしますか?フィールドの初期化に成功すると、このチェックを取り除くことができますよね?
残念ながら、製品言語の大部分では、実行時に関数を変更することはできません。特に、関数本体から単一の命令を追加または削除することはできませんが、賢明に使用すると役立ちます。ただし、C#では、デリゲート(最初にそれらを発見し、その後、ネイティブ言語が関数ポインターを持つ理由に気づきました)とイベントメカニズムを使用して、そのような動作を模倣し、結果としてパフォーマンスが低下する可能性があります.nullチェックは下位レベルに移動するだけですが、完全には消えません。LISP や Prolog などの一部の言語では、コードを簡単に変更できますが、プロダクション言語として扱うことはほとんどできません。
Delphi や C/C++ などのネイティブ言語では、セーフとラピッドの 2 つの関数を記述し、それらをポインタで呼び出し、初期化後にこのポインタをラピッド バージョンに切り替える方がよいようです。追加の頭痛の種なしに、コンパイラまたは IDE がこれを行うためのコードを生成できるようにすることもできます。ただし、@hvd が述べたように、CPU はこれらの関数がほぼ同じであることを認識しないため、速度が低下する可能性があり、キャッシュにプリフェッチされません。
はい、私は好奇心を養うために、明示的な問題のないパフォーマンスを求めているパフォーマンスマニアです。そのような機能を開発するために、どのような一般的なアプローチが存在しますか?