3

在仔细阅读遗留源时,我发现了这一点:

DataSet myUPC = new DataSet();
myUPC = dbconn.getDataSet(dynSQL);

Resharper 正确地将其中的“new Dataset()”部分“变灰”,并建议“删除冗余初始化程序”,但它就这么无害吗?编译器是否只是在第二次分配之前处理第一个实例?IOW,第一个任务是完全没有必要的,还是可能有害的?

4

6 回答 6

11

编译器是否只是在第二次分配之前处理第一个实例?

不,这里没有自动处置。

IOW,第一个任务是完全没有必要的,还是可能有害的?

它在两个小方面有害:

  • 它为初始化代码和垃圾收集器做了更多的工作。它不太可能很重要,但它就在那里。如果构造函数获得了一些可能更严重的本机资源。
  • 它使您的代码看起来像是想做一些实际上并不想做的事情。你不想创建一个新的 empty DataSet,那为什么要这样做呢?

只需使用您真正想要的值初始化变量:

DataSet myUPC = dbconn.getDataSet(dynSQL);

现在您的代码准确地显示了您想要做什么。(请注意,我会修复方法名称,使其遵循 .NET 命名约定。)

于 2013-02-25T22:31:21.930 回答
4

这通常是不必要的。

如果DataSet构造函数启动了一些长时间运行的后台线程或分配了大量内存,这些内存将一直存在,直到冗余对象被垃圾收集,这将是积极有害的,这不是瞬时的。

但是,有礼貌的构造函数不应该做这些事情,所以你可能是安全的。但是,每当我看到这一点时,我都会记下并修复代码,正如 Jon Skeet 指出的那样,它会使您的代码做不必要的工作,创建和处置您无意使用的对象,并且看起来您缺少一些代码.

于 2013-02-25T22:31:09.300 回答
3

IOW,第一个任务是完全没有必要的,还是可能有害的?

第一次分配是不必要的,但也可能有害,具体取决于类型。第一个实例将有资格进行 GC,但仍会被初始化(无缘无故)并且从未使用过。

于 2013-02-25T22:30:53.437 回答
1

它会一直徘徊,直到它被垃圾收集,因为没有其他引用它。但是,如果构造函数有副作用(大概DataSet' 构造函数没有),它也可能是有害的。

于 2013-02-25T22:31:21.830 回答
1

myUPC 被 dbconn.getDataSet() 的输出覆盖。这是因为 getDataSet() 是一个工厂方法,它返回一个 Dataset 类型的对象。

于 2013-02-25T22:31:29.127 回答
1

是的,正如其他答案所示,它实际上有点有害,主要是因为它分配了一个从未使用过的对象,并且最终必须被垃圾收集。但让我更详细一点。

一审可以处理吗?

  DataSet myUPC = new DataSet();
  myUPC = dbconn.getDataSet(dynSQL);

编译器是否只是在第二次分配之前处理第一个实例?

假设您的意思是通过处置收集新的未使用实例的 GC(垃圾收集器),那么答案是:。让我详细说明:

GC 可以在它喜欢的任何时候运行,例如当堆即将满时,或者当试图分配一个不适合堆剩余空间的对象时。因此,GC 也可能(只是偶然)恰好在您的第一条语句和第二条语句之间运行。但是,这不会收集您的new DataSet()对象,因为在局部变量中有对它的引用myUPC。只有在没有对它的引用时才考虑收集对象1

1 ) 实际上,只有在没有从所谓的到对象的引用链时才考虑收集对象。根包括静态字段、方法参数、局部变量和评估堆栈。

可以优化构造函数调用吗?

DataSet myUPC; /* Optimized away? */
myUPC = dbconn.getDataSet(dynSQL);

此外,Just-In-Time 编译器不能简单地优化构造函数调用,因为它可能会影响被初始化对象以外的其他事物(即具有副作用)。例如,如果编译器优化了构造函数调用,那么构造函数将不会在控制台上打印任何内容。这是不希望或不期望的,因此构造函数调用必须保留在那里并产生一个新实例。

class MyClass
{
    public MyClass()
    {
        Console.WriteLine("Constructor called!");
    }
}

abstract class X
{
    void Do()
    {
        MyClass my = new MyClass();  // Should always print "Constructor called!"
        my = GetMyClass();
        // ...
    }

    protected abstract MyClass GetMyClass();
}
于 2013-02-26T01:03:16.803 回答