0

現在、次のような静的ファクトリメソッドがあります。

public static Book Create(BookCode code) {
    if (code == BookCode.Harry) return new Book(BookResource.Harry);
    if (code == BookCode.Julian) return new Book(BookResource.Julian);
    // etc.
}

私がそれらをキャッシュしない理由は、BookResourceが文化に敏感であり、文化は呼び出しごとに変わる可能性があるためです。文化への変更は、返される本のオブジェクトに反映する必要があります。

これらのifステートメントを実行すると、速度のボトルネックになる可能性があります。しかし、本のコードを無名関数/デリゲートにマップするとどうなるでしょうか?次のようなもの:

delegate Book Create();
private static Dictionary<BookCode, Delegate> ctorsByCode = new Dictionary<BookCode, Delegate>();
// Set the following somewhere
// not working!
ctorsByCode[BookCode.Harry] = Create () => { return new Book(BookResource.Harry); }
// not working!
ctorsByCode[BookCode.Julian] = Create () => { return new Book(BookResource.Julian); } 
public static Book Create(BookCode code) {
    return (Book)ctorsByCode[code].DynamicInvoke(null);
}

Create() => {これらの行を実際に機能させるにはどうすればよいですか?

ブックコードが50未満(つまり、ifステートメントが50未満)の場合、これは速度的に価値がありますか?

これも同様の質問ですが、残念ながら、作成者は自分のコードEnum、Delegate Dictionaryコレクションを投稿していません。ここで、delegateはオーバーロードされたメソッドを指しています。

アップデート

いくつかのパフォーマンスベンチマークifs対デリゲートを行いました。ユニットコードをランダムに選び、両方の方法で同じシードを使用しました。デリゲートバージョンは実際には少し遅いです。それらの代表者は、ある種のオーバーヘッドを引き起こしています。実行にはリリースビルドを使用しました。

5000000 iterations
CreateFromCodeIf ~ 9780ms
CreateFromCodeDelegate ~ 9990ms
4

3 に答える 3

2

このような:

private static readonly Dictionary<BookCode, Func<Book>> ctorsByCode = new Dictionary<BookCode, Func<Book>>();

...

ctorsByCode[BookCode.Harry] = () => new Book(BookResource.Harry);

public static Book Create(BookCode code) {
    return ctorsByCode[code]();
}

タイプはFunc<Book>事前定義されたジェネリックデリゲートタイプであり、独自に作成する代わりに使用できます。
また、ディクショナリには、基本Delegateクラスではなく、特定のデリゲートタイプが含まれている必要があります。

ラムダ式は型指定されていない式ですが、デリゲート型が期待される場所(インデクサーの割り当てなど)で使用でき、デリゲートの型を暗黙的に想定します。

あなたも書くことができます

ctorsByCode[BookCode.Harry] = new Func<Book>(() => new Book(BookResource.Harry));

BookResource次のように、代わりにsを含むように辞書を変更することをお勧めします。

private static readonly Dictionary<BookCode, BookResource> codeResources = new Dictionary<BookCode, BookResource>();

...

codeResources[BookCode.Harry] = BookResource.Harry;

public static Book Create(BookCode code) {
    return new Book(codeResources[code]);
}
于 2010-08-29T01:47:54.250 に答える
2

率直に言って、おそらく2つの間のパフォーマンスの違いにはあまり気付かないでしょう。ただし、「機能」バージョンを使用する場合は、ジェネリックを使用するだけでDelegateなく、作成したデリゲートを渡します。したがって、これはあなたの(より単純な)コードになります:

delegate Book Create();
private static Dictionary<BookCode, Create> ctorsByCode 
    = new Dictionary<BookCode, Create>();

ctorsByCode[BookCode.Harry] = () => new Book(BookResource.Harry);
ctorsByCode[BookCode.Julian] = () => new Book(BookResource.Julian); 

public static Book Create(BookCode code) {
    return ctorsByCode[code]();
}
于 2010-08-29T01:51:37.403 に答える
0

ランダムガイ、どうしてそんなに複雑にするの?あなたの質問とそれに続く回答でこの混乱を避ける2つの方法。

  1. BookResource bookResourceEnum = (BookResource)Enum.Parse(typeof(BookResource),bookCode);

    新しい本(bookResourceEnum)を返します。

  2. または、静的ファクトリ メソッド Create が BookCode の代わりに BookResource を受け入れるようにし、クライアントがコードから列挙型への変換について心配できるようにして、BookResource にマップできないコードを誰も渡さないようにします。

真剣に、50 個の「if」またはさらに悪いことに 50 個の「delegate」を含むコードを書いてくれたら、「話」をすることになります。それがボトルネックであると確信できない場合は、時期尚早の最適化 (ある場合) を避けるようにしてください。可読性と保守性が最優先されるべきです。

于 2010-08-30T13:21:21.177 に答える