这是带返回的方法中的有效对象处理代码模式吗?
本文关键字:代码 处理 模式 对象 返回 方法 有效 | 更新日期: 2023-09-27 18:30:40
我在 C# 项目中注意到以下对象处理代码模式,我想知道它是否可以接受(尽管它有效)。
public object GetData()
{
object obj;
try
{
obj = new Object();
// code to populate SortedList
return obj;
}
catch
{
return null;
}
finally
{
if (obj != null)
{
obj.Dispose();
obj = null;
}
}
}
对于此示例,我在项目中使用通用的"对象"而不是实际的 IDisposable 类。
我知道"final"块每次都会被执行,即使返回值也是如此,但它会以任何方式影响返回值(或者它会是一个新的对象实例),因为对象被设置为 null(对于似乎是对象处置和 GC 目的)。
更新 1:
我尝试了以下代码片段,返回对象是非空的,尽管本地对象设置为 null,所以它可以工作,考虑到下面的一些评论,这有点奇怪:
public StringBuilder TestDate()
{
StringBuilder sb;
try
{
sb = new StringBuilder();
sb.Append(DateTime.UtcNow.ToString());
return sb;
}
catch
{
return null;
}
finally
{
sb = null;
}
}
顺便说一句,我正在使用 C# 4.0。
附言我只是在审查这个项目代码。我不是原作者。
更新 2:
找到了这个谜团的答案[1]。finally 语句被执行,但返回值不受影响(如果在 finally 块中设置/重置)。
[1] 在尝试 { 返回 x; } 最后 { x = null; } 语句中到底发生了什么?
这段代码可以很好地编译(假设你实际上不是在用Object
而是在实现IDisposable
的东西),但它可能不会做你想要它做的事情。在 C# 中,没有new
不会得到一个新对象;此代码将返回对已释放对象的引用,并且根据对象和 Dispose() 实际执行的操作,尝试使用已释放的对象可能会也可能不会使程序崩溃。
我假设这个想法是创建一个对象,用它做一些事情,然后在失败时返回对象(如果成功或 null)(并释放对象)。如果是这样,您应该做的是:
try {
obj = new MyClass();
// ... do some stuff with obj
return obj;
}
catch {
if(obj != null) obj.Dispose();
return null;
}
简单地使用 using
语句即可获得与此相同的结果,并且是标准做法
public int A()
{
using(IDisposable obj = new MyClass())
{
//...
return something;
}
}
但是,我建议不要返回您的 IDisposable 对象。当您处置一个对象时,它应该被视为"不可用"。那么,为什么要归还它呢?
如果对象的生存期需要长于方法A
生存期,请考虑让调用方法B
实例化对象,并将其作为参数传递给方法 A
。在这种情况下,方法 B
将是使用 using
语句的方法,它将在其中调用 A
。
如果要返回 IDisposable 对象,则调用方负责释放它:
public IDisposable MakeDisposableObject()
{
return new SqlConnection(""); // or whatever
}
访客:
using (var obj = MakeDisposableObject())
{
}
您的方法释放一个对象然后返回它几乎没有意义。释放的对象对调用方没有价值。通常,引用已处理的一次性物品应产生ObjectDisposedException
。
一些观察。
该代码无法编译,因为object
没有.Dispose()
方法。
你为什么不使用IDisposable
?
为什么要释放正在返回的对象,因为返回会返回一个对象,以便其他代码使用它。"处置"某物的概念是让它有机会清理自身及其使用的、未托管的资源。如果您返回的对象应该在其他地方使用,但具有要在其他任何地方使用该对象之前清理的非托管资源,那么您实际上应该有 2 个单独的对象。一个用于加载一些可丢弃的数据,另一个对象将包含要传递的可用加载内容。这方面的一个例子是 .NET 框架中的流读取器。您通常会new
流读取器,将其读入byte[]
或其他数据对象,.Dispose()
流读取器,然后return
byte[]
。具有一些资源需要及时处置的"加载器"与包含"加载"数据的对象是分开的,后者无需释放即可使用。