1

はい、私は知っています、可変オブジェクトについてのさらに別の質問。一般的な背景についてはこれを、私の質問に最も近い類似物についてはこれを参照してください。(ただし、ここでは適用されないC ++固有の倍音がいくつかあります)

次の擬似コードが最良のインターフェース設計を表していると仮定しましょう。つまり、これはビジネスセマンティクス(現在の状態)をOOタイプに最も明確に表現したものです。当然のことながら、UglyDataとそれを使用して実行するタスクは、段階的に変更される可能性があります。

public class FriendlyWrapper
{
    public FriendlyWrapper(UglyDatum u)
    {
        Foo = u.asdf[0].f[0].o.o;
        Bar = u.barbarbar.ToDooDad();
        Baz = u.uglyNameForBaz;
        // etc
    }

    public Widget Foo { get; private set; }
    public DooDad Bar { get; private set; }
    public DooDad Baz { get; private set; }
    // etc
    public WhizBang Expensive1 { get; private set; }
    public WhizBang Expensive2 { get; private set; }

    public void Calculate()
    {
        Expensive1 = Calc(Foo, Bar);
        Expensive2 = Calc(Foo, Baz);
    }

    private WhizBang Calc(Widget a, DooDad b) { /* stuff */ }

    public override void ToString()
    {
        return string.Format("{0}{1}{2}{3}{4}", Foo, Bar, Baz, Expensive1 ?? "", Expensive2 ?? "");                             
    }
}

// Consumer 1 is happy to work with just the basic wrapped properties
public string Summarize()
{
    var myStuff = from u in data
                  where IsWhatIWant(u)
                  select new FriendlyWrapper(u);

    var sb = new StringBuilder();
    foreach (var s in myStuff)
    {
        sb.AppendLine(s.ToString());
    }
    return sb.ToString();
}

// Consumer 2's job is to take the performance hit up front.  His callers might do things 
// with expensive properties (eg bind one to a UI element) that should not take noticeable time. 
public IEnumerable<FriendlyWrapper> FetchAllData(Predicate<UglyDatum> pred)
{
    var myStuff = from u in data
                  where pred(u)
                  select new FriendlyWrapper(u);

    foreach (var s in myStuff)
    {
        s.Calculate();  // as written, this doesn't do what you intend...
    }

    return myStuff;
}

ここでの最良のルートは何ですか?私が見ることができるオプション:

  1. 上記のように、明示的なCalculate()メソッドを使用した可変オブジェクト
  2. 高価な計算がゲッターで行われる(そしておそらくキャッシュされる)可変オブジェクト
  3. 一方が他方から継承する(またはおそらく構成する?)2つのオブジェクトに分割します
  4. 上にリンクされたC++の質問のように、ある種の静的+ロックメカニズム

私は自分自身で#2に傾いています。しかし、すべてのルートには潜在的な落とし穴があります。

#1または#2を選択した場合、可変性に対するConsumer2のループを明確で正しい方法でどのように実装しますか?

#1または#3を選択した場合、一部のプロパティのみを計算し、他のプロパティは計算したくない将来の状況をどのように処理しますか?N個のヘルパーメソッド/派生クラスを作成しますか?

#4を選んだら、あなたは頭がおかしいと思いますが、気軽に説明してください

4

1 に答える 1

1

あなたの場合、LINQを使用しているので、計算が必要な場合にのみこれらのオブジェクトを作成します。

それがあなたの標準的な使用パターンであるなら、私はただ高価な計算をコンストラクターに直接置くでしょう。計算しない場合がない限り、レイジー初期化の使用は常に遅くなります。ゲッターで計算を行っても、何も保存されません(少なくともこの特定のケースでは)。

可変性に関しては、参照構文とIDを持つ可変オブジェクト(つまり、C#のクラス)は本当に問題ありません。可変値型(つまり、構造体)を扱う場合は、さらに問題になります。.NET BCLには非常に多くの可変クラスがあり、問題は発生しません。値型を扱い始めるとき、問題は通常、1つ以上です。可変値型は、非常に予期しない動作を引き起こします。

一般的に、私はこの質問を逆さまにします-このオブジェクトをどこでどのように使用しますか?使いやすさに影響を与えることなく、このオブジェクトを(問題があると判断された場合)最もパフォーマンスの高いものにするにはどうすればよいですか?1)、3)、4)のオプションはすべて使い勝手が悪くなるので、避けたいと思います。この場合、2)を実行しても効果はありません。コンストラクターに入れるだけなので、オブジェクトは常に有効な状態になります(これは使いやすさと保守性に非常に優れています)。

于 2009-06-12T15:58:02.443 に答える