0

这是一个愚蠢的错误:

List<Foo> fooList = new List<Foo>();
Foo f = new Foo();
while (something.Read()) {
    f.Fill(something.GetRecord());
    fooList.Add(f);
}

当然,我应该在循环内实例化一个新的 Foo 。

编译器可以在编译时检测到这种错误吗?

对于天真的眼睛,它看起来应该能够检测到这种行为(在循环中用相同对象的实例填充 List)。然后它应该发出一个警告,比如“你用同一个实例多次填充一个容器。”。

那么,我有多天真呢?你知道存在这样的语言吗?

4

2 回答 2

2

是的,这是可能的。

但是,我认为工具或编译器本身不会对此发出警告,因此您必须使用可以通过您自己的分析进行扩展的工具。对于 Java,FindBugs就是这样一个工具。对于 C、C++ 等,gcc 4.5 将允许人们编写自己的扩展插件,LLVM 的clang也是为此而设计的。还有来自 Mozilla 的Dehydra,同样适用于 C++。对于 MS 语言,有Phoenix 框架

所以问题是,你如何写这个分析?这有点棘手,并且取决于工具。但基本上:

  • 您可以相当容易地检测到循环(查找“强连接组件”),
  • 别名分析可以告诉您一个特定的变量或参数是指一个对象还是多个对象(也许是寻找“抽象对象”),
  • 您可以使用对象或变量的静态类型找到正确的容器。

因此,您可以很容易地检测到List<>.append(x)循环中的调用,其中 x 只能引用一个对象。

于 2009-09-24T11:29:05.450 回答
2

如果你想用一个对象的多个实例填充一个 List<> 怎么办?您是否需要装饰您的代码,#pragma以便编译器让您一个人呆着?

你怎么会声明一个类有这些限制呢?List<> 实际上只不过是一个 C# 类,您可以反编译 mscorlib.dll 并查看其完整实现。所以要拥有这种知识,它必须在某个地方进行硬编码。属性?那将是令人难以置信的限制。验证代码的特殊方法?会给你的对象增加开销。

这种东西永远不会(我的意思是永远不会)使用是有原因的:在极少数情况下,它会有所帮助而不是阻碍,远没有超过它在两种实施难度(框架本身和您的代码)和性能损失(来自必须在 GC 执行其操作时在内存中移动的过度膨胀的对象)。

于 2009-09-23T12:06:44.850 回答