这是带返回的方法中的有效对象处理代码模式吗?

本文关键字:代码 处理 模式 对象 返回 方法 有效 | 更新日期: 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[]。具有一些资源需要及时处置的"加载器"与包含"加载"数据的对象是分开的,后者无需释放即可使用。