孙展波:实现.NET无限潜力

Realize .NET Potential (中文版)
随笔 - 430, 评论 - 12203, 引用 - 54

导航

关于

贴子以"现状"提供且没有任何担保也没有授予任何权利。
计数器(2005/12/8起).点击阅读我的Blog In English

标签

每月存档

最新留言

广告

 

如果我们有如下的类定义:

public abstract class FruitBase {

}

 

public class Apple : FruitBase {

}

 

public class Orange : FruitBase {

}

 

public class FruitCollection : System.Collections.ObjectModel.Collection<FruitBase> {

}

 

public class Menu {

    public FruitCollection Fruits { get; set; }

}

对于Menu的一个实例,比如olympicMenu,其Fruits属性可能只含有Apple,但是也许全是Orange,或者是多种FruitBase字类实例的集合。

如果我们还定义了Fruit这样一个类:
public class Fruit : FruitBase {

}

 

这样就很有可能让一些程序员产生错觉了,以为Apple, Orange都是Fruit的子类。而MenuFruits这个名字,似乎也提示其是Fruit的集合,而不是FruitBase的集合。

 

在一个需要对olympicMenu.Fruits中的每个实例进行检查的代码中,如果程序员忘掉了这一点,就可能会写出这样的代码:

 

for (int i = 0; i < olympicMenu.Fruits.Count; i++) {

    Fruit f = olympicMenu.Fruits[i];

//...Op on f

}

 

幸运的是,编译器会给出这样的错误信息:Cannot implicitly convert type ‘FruitBase’ to ‘Fruit’. An explicit conversion exists (are you missing a cast?)

 

因为explicit必须显示写出,程序员的错误得以避免。但是,foreach显然是要比for循环更简练。如以下的代码所示:

 

foreach (Fruit f in olympicMenu.Fruits) {

//...Op on f

}

这个代码却不再会得到编译器的错误提示了!foreach隐含了显式的类型转换!编译通过!如果在调试运行时olympic.Fruits的元素都是Fruit类型,这个错误也不能在调试时发现。这样发布的产品就有了这样一个bug。在运行时,如果olympic.Fruits含有Orange, Apple类的实例时,InvalidCastException将会出现。

 

FruitBase这个抽象类,就这样又被人记起了。

 

===

写这个blog,是因为今天分析了一个在已经发布的SP1中的bugVS 2008 SP1的代码中并没有FruitBase, Fruit, Apple, Orange, 但与之相对应的有WPF中的:TriggerBase, Trigger, MultiTrigger, DataTrigger.

 

这行代码,

foreach (Trigger trigger in curStyle.Triggers)

导致了一个需要通过发布补丁的大bug. 成本是很大的。如果Trigger的命名是PropertyTrigger,不但可能避免这个混淆,而且也更加精确地描述了其功用。

 

回想几年前WPF还在开发的时候,我就提出过这一意见。当然有支持的声音。但是最后还是用Trigger这个名字了。其最有力的理由是什么呢?

 

且听微软实录下一篇。

打印 | 张贴于 2008-09-06 08:32:43 | Tag:C#

留言反馈

暂时没有留言纪录
博客主人设置本博客不允许匿名用户发表言论,请登录后再试

Powered by: Joycode.MVC引擎 0.5.2.0