9

どちらが良いですか???

public class Order
{
   private double _price;
   private double _quantity;

  public double TotalCash
  {      
   get
   {
    return _price * _quantity;
   }
}

また

public class Order
{

   private double _totalCash;
   private double _price;
   private double _quantity;

  private void CalcCashTotal()
 {
   _totalCash = _price * _quantity
 }

  public double Price
  {      
   set
   {
     _price = value;
     CalcCashTotal();
   }
  }

  public double Quantity
  {      
   set
   {
     _price = value;
     CalcCashTotal();
   }
  }


  public double TotalCash
  {      
   get
   {
    return _totalCash;
   }
}
4

13 に答える 13

14

There are tradeoffs. If the calculations simple and does not take a long time, then put it in the get. It makes your life easier, because you don't have to worry about doing the check in every set that total price is dependant on, which could lead to mistakes.

If the calculation takes a lot of time, then you could also take a hybrid approach. You could set a IsDirtyTotalPrice boolean in all the dependant sets, and then do the calculation on the fly in the get and cache it so that the get only calculates the variable when it needs to. You don't do the calculation in the sets because there could be a lot of them, and you wan to do the calculation as few times as possible.

  public class Order
  {
     private double _totalCash;
     private double _price;
     private double _quantity;
     private _IsDirtyTotalCash = true;

  private void CalcCashTotal()
  {
    _totalCash = _price * _quantity
  }

  public double Price
  {      
   set
   {
     _price = value;
     _IsDirtyTotalCash = true;
   }
  }

  public double Quantity
  {      
   set
   {
     _price = value;
     _IsDirtyTotalCash = true;
   }
  }

  public double TotalCash
  {      
   get
   {
        if(_IsDirtyTotalCash)
    {
      _totalCash = CalcTotalCost();
       _isDirtyTotalCash = false;
     }
     return _totalCash;
   }
  }

}
于 2009-01-15T05:16:50.617 に答える
4

それらが生成する値は内部に保存され、一度だけ計算する必要があるため、通常、私はそれらをセットに入れようとします。クエリを実行するたびに値が変化する可能性がある場合にのみ、get に計算を配置する必要があります。

価格/数量の例では、価格または数量が設定されたときに数量を再計算する単一の個別のメソッドを実際に持つことができます。

于 2009-01-15T04:59:58.187 に答える
3

私はチャールズ・グラハムのハイブリッド提案に賛成しますが、その理由について2セントを追加したいと思います。

上記の提案の多くは複雑さと最適化について語っていますが、クラスのコンシューマーを考慮に入れると、これがすべて窓の外に出るのを忘れてください。あなた唯一の消費者であり、最初の実装を使用した場合、次のことを覚えている可能性があります。

double subTotal = myOrder.TotalCash;
double tax = subTotal * 0.05;
double shipping = subTotal > 100 ? 0 : 5.95;
double grandTotal = subTotal + tax + shipping;
OutputToUser(subTotal, tax, shipping, grandTotal);

他の人はそうではないかもしれません。それmyOrder.TotalCashがメソッドではなくプロパティであることがわかると、少なくともキャッシュされた値であると思います。つまりsubTotal、上記の例でのアクセスは、アクセスと同等の効率myOrder.TotalCashです。舞台裏で計算が行われていることに気づかず、彼らは次のように書いています。

double tax = myOrder.TotalCash * 0.05;
double shipping = myOrder.TotalCash > 100 ? 0 : 5.95;
double grandTotal = myOrder.TotalCash + tax + shipping;
OutputToUser(myOrder.TotalCash, tax, shipping, grandTotal);

myOrder.TotalCash小計を表すために残します。現在、1回ではなく4回計算されています。

要約すると、プロパティが変数またはキャッシュされた値を表し、メソッドが何かを処理して値を返すと信じているのは私だけではないと確信しています。CalculateTotalCash()パフォーマンスの低下が予想されるため、保存して1回だけ呼び出すのが理にかなっています。一方、TotalCashキャッシュされた値であることが期待され、自由にアクセスできます。したがって、変更されたときにのみ再計算することが重要TotalCashです。

読み取りの間に複数のセットがある場合は、ハイブリッド提案が優先されます。そうすれば、捨てられる値を計算する時間を無駄にすることはありません。

于 2009-01-15T05:59:32.120 に答える
3

プロパティを導出/計算する必要があるかどうかを判断するときは、計算時の値を保持する必要があるかどうかを考慮することが重要です。

TotalCashの場合、計算のためにビジネスロジックが変更された場合、既存のレコードに対してTotalCashプロパティをさかのぼって変更することは望ましくない場合があります。

ただそれをそこに出す...

于 2009-01-15T05:59:35.913 に答える
3

次の理由により、最初のほうが優れています。

  • 短いです。
  • 理解しやすいです。
  • 価格または数量が設定されるたびに TotalCash を再計算するのは少しおこがましいです。可能な限り怠惰で、要求されたときにのみ計算する必要があります。

そうは言っても、計算をセッターに入れると効果的にキャッシュされるため、パフォーマンスの問題が発生した場合は、(明確さを犠牲にして) 有用な変更になる可能性があります。

于 2009-01-15T05:02:04.733 に答える
2

The first, because:
1) Less code is better;
2) Less complexity;
3) Less variables helps to get less colateral problems;
4) The property will be always updated;
5) If you change "CalcCashTotal" procedure name you get more another points to change...

于 2009-01-15T05:09:11.507 に答える
1

場合によります。アプリケーションは読み取りが重いですか、それとも書き込みが重いですか?計算は高額ですか?計算が高価で、アプリケーションの読み取りが多い場合は、セットで実行してください。そうすれば、計算ペナルティを数回支払うだけです(読み取りと比較して)。

于 2009-08-24T03:51:50.223 に答える
1

Putting it on the get function is not very ideal. You will be recalculating it for no reason. It doesn't even make any more sense. So here is a case where ::gasp:: optimization makes sense and is preferred. Calculate it once and reap the benefits.

于 2009-01-15T05:10:23.750 に答える
1

I've always been told that if there is considerable work or calculation being done, that you should do it in a method. There's no major compiler/runtime advantages as far as I know, but it will make more sense to the consumer of the code. A property that takes a while to return the value to me would throw up a red flag that something could be wrong.

That's my 2 cents... but even I would probably just go with your first example if the class is really that simple :-)

于 2009-01-15T05:18:26.103 に答える
1

The first option is better. The difference in "optimization" is minuscule. Not to mention, what if setting occurs over and over but you only ever need to get TotalCost once? I'd be more concerned about lost developer hours trying to debug the class once it becomes very complex.

But there is an important time when the second option is needed, specifically when the calculated value changes the calculated objects. I'm having a hard time coming up with an example, so I'll use a real-life one where the number of bays in a wall is determined by its width.

class Wall {
    public decimal Width {
       get {
           ...
       }
       set {
           ValidateChanges();
           width = value;
           CreateBays();
       }
    }

    public Bays[] Bays {
       get {
           ...
       }
       set {
           ValidateChanges();
           ...
       }
    }

    private void CreateBays() {
        // Delete all the old bays.
        ...
        // Create a new bay per spacing interval given the wall width.
        ...
    }
}

Here, every time the width changes the bays in the wall are recreated. If this occurred on Bay.getter it would be fairly disastrous for the properties of the Bay object. The getter would have to figure out if the width has changed or not since the last get statement, increasing complexity.

于 2009-01-15T05:19:29.003 に答える
0

読み取り専用の get または set を計算します。

プロパティは、バッキング変数があるように動作する必要があるという意見です。

読み取りに時間がかかる計算は好きではありません。

于 2009-01-15T04:59:21.400 に答える
0

ほとんどの場合、コードが少ないほど良いため、TotalCash の getter で計算を行うアプローチを採用します。また、TotalCash の値が常に正しいことも保証します。不自然な例として、別のメソッド NewOrder(Price, Qty) があり、このメソッドの最後で CalculateTotal を呼び出すのを忘れた場合、TotalCash の値が正しくない結果になる可能性が非常に高くなります。

計算の処理に時間がかかり、1 つまたは 2 つのプロパティの値を変更するだけで再計算が必要になる場合は、setter で計算する方がよい場合がありますが、ほとんどの場合、エラーの余地が少ない方法を使用することをお勧めします。実行に少し時間がかかります。

于 2009-01-15T05:03:04.933 に答える
0

私のルール、そして誰にでもこれをお勧めします:

メソッド = 副作用あり ゲッター = 副作用なし (例外メモ化 - ゲッターでも許可されています)

于 2010-07-06T09:58:09.073 に答える