3

かなりの数のケースで、変数を設定する前に IF チェックを実行する必要があるかどうか (およびメソッドの複雑さを増加させる必要があるかどうか)、またはこれが Windows またはフレームワークによって内部的に行われるかどうか疑問に思っている状況に陥っています。

例として、フォームのイベントなど、常にトリガーされるイベントがあるとしますMouseMove。これらの方法のどれを使用するのが良いでしょうか? 呼び出しthis.Cursor = Cursors.SizeNWSE;は内部的にもチェックされ、必要のない場合はアクションが実行されないことを確認していますか、それともやみくもにコードを実行していますか?

例 A:

private void Form1_MouseMove(object sender, MouseEventArgs e)
{
    if (e.X - this.Width > -16 && e.Y - this.Height > -16)
    {
        this.Cursor = Cursors.SizeNWSE;
    }
    else
    {
        this.Cursor = Cursors.Arrow;
    }
}

例 B:

private void Form1_MouseMove(object sender, MouseEventArgs e)
{
    if (e.X - this.Width > -16 && e.Y - this.Height > -16)
    {
        if (this.Cursor != Cursors.SizeNWSE)
            this.Cursor = Cursors.SizeNWSE;
    }
    else
    {
        if (this.Cursor != Cursors.Arrow)
            this.Cursor = Cursors.Arrow;
    }
}
4

3 に答える 3

2

.NET フレームワークは、プロパティを設定する前にチェックしません。Cursora のを設定するための逆コンパイルされたコード スニペットを次に示しますForm

      set
      {
        Cursor cursor1 = (Cursor) this.Properties.GetObject(Control.PropCursor);
        Cursor cursor2 = this.Cursor;
        if (cursor1 != value)
        {
          System.Windows.Forms.IntSecurity.ModifyCursor.Demand();
          this.Properties.SetObject(Control.PropCursor, (object) value);
        }
        if (this.IsHandleCreated)
        {
          System.Windows.Forms.NativeMethods.POINT pt = new System.Windows.Forms.NativeMethods.POINT();
          System.Windows.Forms.NativeMethods.RECT rect = new System.Windows.Forms.NativeMethods.RECT();
          System.Windows.Forms.UnsafeNativeMethods.GetCursorPos(pt);
          System.Windows.Forms.UnsafeNativeMethods.GetWindowRect(new HandleRef((object) this, this.Handle), out rect);
          if (rect.left <= pt.x && pt.x < rect.right && (rect.top <= pt.y && pt.y < rect.bottom) || System.Windows.Forms.UnsafeNativeMethods.GetCapture() == this.Handle)
            this.SendMessage(32, this.Handle, (IntPtr) 1);
        }
        if (cursor2.Equals((object) value))
          return;
        this.OnCursorChanged(EventArgs.Empty);
      }
    }

毎回実行されるコードの束があることがわかります。プロパティが変更されたかどうかを確認するチェックがありますが、フレームワークの実行が数行停止するだけです。

于 2013-05-30T17:46:26.987 に答える
2

いいえ、なぜですか?.NET がそのように動作する理由はまったくありません。同じ値を「上書き」するのを防ぐために代入する前に何かを比較すると、複雑さが増し、パフォーマンスが低下する可能性があります。実際のパフォーマンスへのマイクロインパクトは、特定の宛先 CPU アーキテクチャ、キャッシュ、タイミング、局所性、その他多くの要因の動作に大きく依存します。

このようなチェックの唯一の理由は、まったく同じ値が特定のプロパティに既に格納されている場合に望ましくないアクション(この例ではプロパティを示す)をトリガーする割り当てがあるかどうかです。Cursor

したがって、そのような動作が必要な場合は、プロパティのセッターにカプセル化することをお勧めします。

public Cursors Cursor
{
    get { return cursor; }
    set
    {
        // prevent reacting to “no change”
        if (cursor != value)
        {
            cursor = value;
            … perform some other action …
        }
    }
}
private Cursors cursor;

結論として、パフォーマンスについて心配する必要はありません。コードのセマンティクスと可読性について心配してください。


更新:別の回答で提供されているテスト コードを実行すると、結果はCore i5 3320M 2.60 GHz CPUでおよそ00:00:00.0800000 から 00:00:00.1500000 の間になります。Mycursorはローカル変数として宣言されています。無条件バージョンの方が高速な場合もあれば、条件付きバージョンの方が高速な場合もあることに注意してください。

OPの場合、複雑な内部プロセスを含むプロパティとして宣言されている場合(OPは「変数」であると述べています)、はい、条件付き割り当てを使用したバージョンは大幅に高速になる可能性があります。ただし、OPの質問はそれを示していませんでした。

実際のソフトウェアでは、カーソルの変更が非常に多いため、1 秒間のパフォーマンスについて考える価値があるとは思えません。

于 2013-05-30T17:37:38.477 に答える