这个有意思的问题出自Eric Gu的Blog。代码如下:
public void TransmitResponse(ArrayList responses,
StreamWriter streamWriter)
{
foreach (DataResponse response in responses)
{
NetworkResponse networkResponse = response.GetNetwork();
networkResponse.Send(streamWriter);
}
GC.Collect(); // clean up temporary objects
}
这段代码问题何在?
原Blog Entry的众多回复非常有意思。首先,有人指出,代码没有关闭NetworkResponse对象和StreamWriter对象,应该在代码中加上“using”来保证正确调用这些对象的Dispose()方法。但是,随即有人指出,在这个方法中调用这些对象的Dispose(),是不正确的。
首先,作为参数的DataResponse集合和StreamWriter对象,根本不能假定它们“应该”在这个方法内部被关闭,也许在调用这个方法之后,其他地方仍然要使用它们。而在循环中通过GetNetwork()方法得到的临时NetworkResponse对象,很难看出GetNetwork()方法是否是创建一个新的NetworkResponse对象抑或只是返回一个已有的对象(还有人指出,如果是创建一个新的对象,那个方法名称应该是CreateNetwork(),而不是GetNetwork()),所以贸然调用它的Dispose()也是不可取的。
最后讨论的结果,这段代码的问题主要是:1、代码中未检测各个相关的对象是否为null,或者ArrayList中的对象是否类型正确;2、调用GC.Collect()毫无理由。
原Blog Entry的众多回复所统一的意见:只有一个方法亲自创建了一个新的对象实例,才有义务调用这个实例的Dispose()。
呵呵,我想到一个典型的“反例”,那就是ADO.NET中DataReader的使用,它的使用者在某些情况下,有义务调用它的Close()方法。当然,作为开发人员,可以利用各种模式来“修正”这个“反例”。比如,这篇文章所介绍的使用Delegate来将DataReader的Dispose责任回收到创建DataReader的地方。