More Effective C# 中文版 副标题: 改善C#程序的50个具体办法 [美] Bill Wagner 著,陈黎夫 译 人民邮电出版社,2010年1月第1版
More Effective C# 中文版,第3章 C#设计实践,条目26:确保属性的行为与数据类似
属性存在着两面性。从外部看上去它就像是简单的数据元素。而在内部,则以方法的形式实现。这种两面性可能会让你创建出让用户感到迷惑的属性。使用你的类型的开发者会假设其中的属性会与直接访问数据成员一样。若你的属性不符合这样的假设,那么用户则可能产生误会。属性给人的感觉应该是和直接访问数据成员一样。
若是能够正确地使用属性来描述数据成员,那么即可符合客户开发者的期待。首先,客户开发者希望相连的两次调用属性的 get 访问器将会得到同样的结果。
int someValue = someObject.ImportantProperty; Debug.Assert(someValue == someObject.ImportantProperty);
当然,多线程环境下该假设可能不会成立──无论是使用属性还是字段。不过其他情况下,重复地访问同样一个属性理应得到同样的结果。
此外,类型的使用者也不会期待属性的访问器做很多工作。调用某个属性的 getter 不应该影响到花费很多的时间。类似地,属性的 set 访问器可能会执行一定的验证,不过也不应该太过耗时。
这个条目是非常有道理的。但是,也存在着例外:DateTime.Now 属性。这个很常用的属性显然不满足:重复地访问同样一个属性理应得到同样的结果。DateTime 类的 Now 属性是静态的,那么让我们来看看Stopwatch.Elapsed 属性吧:
01: using System; 02: using System.Diagnostics; 03: 04: sealed class Test 05: { 06: static void Main() 07: { 08: Console.WriteLine("OS Version: " + Environment.OSVersion); 09: Console.WriteLine("CLR Version: " + Environment.Version); 10: Console.WriteLine("IsHighResolution: " + Stopwatch.IsHighResolution); 11: Console.WriteLine("Frequency: {0:N0}", Stopwatch.Frequency); 12: var stopwatch = Stopwatch.StartNew(); 13: Console.WriteLine("Elapsed: " + stopwatch.Elapsed); 14: Console.WriteLine("Elapsed: " + stopwatch.Elapsed); 15: stopwatch.Stop(); 16: } 17: }
该程序在 Linux 操作系统中的运行结果如下:
OS Version: Unix 2.6.32.24 CLR Version: 2.0.50727.1433 IsHighResolution: True Frequency: 10,000,000 Elapsed: 00:00:00.0000993 Elapsed: 00:00:00.0013385
该程序在 Windows 操作系统中的运行结果如下:
OS Version: Microsoft Windows NT 6.0.6002 Service Pack 2 CLR Version: 4.0.30319.1 IsHighResolution: True Frequency: 14,318,180 Elapsed: 00:00:00.0000245 Elapsed: 00:00:00.0260632
可见 Stopwatch 类的 Elapsed 属性也不满足:重复地访问同样一个属性理应得到同样的结果。
上述程序的运行环境如下所示:
版权声明:本文为博主http://www.zuiniusn.com 原创文章,未经博主允许不得转载。
时间: 2024-11-14 04:13:56