C#Properties,为什么在赋值之前检查是否相等

为什么我看到人们实现这样的属性?
检查该值是否等于当前值的重点是什么?

public double? Price { get { return _price; } set { if (_price == value) return; _price = value; } } 

在这种情况下,这将是没有意义的; 然而,在存在相关副作用(通常是事件)的情况下,它避免了微不足道的事件。 例如:

 set { if (_price == value) return; _price = value; OnPriceChanged(); // invokes the Price event } 

现在,如果我们这样做:

 foo.Price = 16; foo.Price = 16; foo.Price = 16; foo.Price = 16; 

我们没有得到4个事件; 我们得到最多1(如果它已经是16,则可能为0)。

在更复杂的示例中,可能存在validation,更改前操作更改后操作。 如果你知道它实际上并不是一个改变,那么所有这些都可以避免。

 set { if (_price == value) return; if(value < 0 || value > MaxPrice) throw new ArgumentOutOfRangeException(); OnPriceChanging(); _price = value; OnPriceChanged(); } 

这不是一个答案,更多:它是对索赔的基于证据的回应(在另一个答案中),检查比分配更快。 简而言之:不,不是。 没有任何区别。 我得到(对于不可为空的int ):

 AutoProp: 356ms Field: 356ms BasicProp: 357ms CheckedProp: 356ms 

(在连续运行中有一些小变化 – 但基本上它们在任何合理的舍入中都需要完全相同的时间 – 当做500万次时,我们可以忽略1ms的差异)

事实上,如果我们改为int? 我明白了:

 AutoProp: 714ms Field: 536ms BasicProp: 714ms CheckedProp: 2323ms 

还是double? (就像在问题中):

 AutoProp: 535ms Field: 535ms BasicProp: 539ms CheckedProp: 3035ms 

所以这不是性能帮手!

通过测试

 class Test { static void Main() { var obj = new Test(); Stopwatch watch; const int LOOP = 500000000; watch = Stopwatch.StartNew(); for (int i = 0; i < LOOP; i++) { obj.AutoProp = 17; } watch.Stop(); Console.WriteLine("AutoProp: {0}ms", watch.ElapsedMilliseconds); watch = Stopwatch.StartNew(); for (int i = 0; i < LOOP; i++) { obj.Field = 17; } watch.Stop(); Console.WriteLine("Field: {0}ms", watch.ElapsedMilliseconds); watch = Stopwatch.StartNew(); for (int i = 0; i < LOOP; i++) { obj.BasicProp = 17; } watch.Stop(); Console.WriteLine("BasicProp: {0}ms", watch.ElapsedMilliseconds); watch = Stopwatch.StartNew(); for (int i = 0; i < LOOP; i++) { obj.CheckedProp = 17; } watch.Stop(); Console.WriteLine("CheckedProp: {0}ms", watch.ElapsedMilliseconds); Console.ReadLine(); } public int AutoProp { get; set; } public int Field; private int basicProp; public int BasicProp { get { return basicProp; } set { basicProp = value; } } private int checkedProp; public int CheckedProp { get { return checkedProp; } set { if (value != checkedProp) checkedProp = value; } } } 

假设我们不处理任何与变更相关的事件。 我不认为比较比分配更快。 这取决于数据类型。 假设你有一个字符串,在最坏的情况下,比例比一个简单的赋值长得多,其中成员只是改变对新字符串的引用的引用。 所以我的猜测是,在这种情况下最好立即分配。 在简单数据类型的情况下,它没有真正的影响。

这样,您不必重新分配相同的值。 它只是更快地执行比较值。 据我所知