0

我在 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 类。

我知道每次都会执行“finally”块,即使返回值也是如此,但是由于对象被设置为 null (用于对象处理和 GC 目的)。

更新1:

我尝试了下面的代码片段,返回对象是非空的,虽然本地对象设置为空,所以它可以工作,考虑到下面的一些评论,这有点奇怪:

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。

PS我只是在审查这个项目代码。我不是原作者。

更新 2:

找到了这个谜团的答案 [1]。finally 语句被执行,但返回值不受影响(如果在 finally 块中设置/重置)。

[1]在 try { return x; 中真正发生了什么?} 最后 { x = null; } 陈述?

4

4 回答 4

5

这段代码可以很好地编译(假设您实际上并没有使用 anObject而是实现的东西IDisposable),但它可能不会做您希望它做的事情。new在 C# 中,没有;你不会得到一个新对象。此代码将返回对已释放对象的引用,并且取决于对象和 Dispose() 实际执行的操作,尝试使用已释放对象可能会或可能不会使您的程序崩溃。

我假设这个想法是创建一个对象,用它做一些事情,然后在成功时返回对象,或者在失败时返回 null(并处置对象)。如果是这样,你应该做的是:

try {
    obj = new MyClass();
    // ... do some stuff with obj
    return obj;
}
catch {
    if(obj != null) obj.Dispose();
    return null;
}
于 2013-09-10T00:57:40.320 回答
2

简单地使用该using语句可以达到与此相同的结果,并且是标准做法

public int A()
{
    using(IDisposable obj = new MyClass())
    {
        //...
        return something;
    }
}

但是,我建议不要返回您的 IDisposable 对象。当你处理一个对象时,它应该被认为是“不可用的”。那么,为什么要退货呢?

如果对象的生命周期需要比方法A的生命周期长,请考虑让调用方法B实例化对象,并将其作为参数传递给方法A。在这种情况下,methodB将是使用该using语句的那个​​,它会在其中调用A.

于 2013-09-10T00:52:16.587 回答
2

如果您要返回 IDisposable 对象,则调用者有责任处理它:

public IDisposable MakeDisposableObject()
{
    return new SqlConnection(""); // or whatever
}

呼叫者:

using (var obj = MakeDisposableObject())
{
}

您的方法处理对象然后返回它几乎没有任何意义。处置的对象对调用者没有任何价值。一般来说,引用一个已被处理的一次性对象应该产生一个ObjectDisposedException.

于 2013-09-10T01:05:24.073 回答
1

几点观察。

该代码无法编译,因为object没有.Dispose()方法。

你为什么不使用IDisposable

您为什么要处置正在返回的对象,因为返回您将返回一个对象以供其他代码使用它。“处置”某物的概念是给它一个机会来清理自己及其使用过的非托管资源。如果您要返回一个应该在其他地方使用的对象,但有非托管资源要在该对象在其他任何地方使用之前清理,那么您真的应该有 2 个单独的对象。一个是加载一些一次性的数据,另一个是包含您想要传递的可用加载内容的对象。这方面的一个例子是 .NET 框架中的流阅读器。您通常会new使用流阅读器,将其读入一个byte[]或其他数据对象,.Dispose()流阅读器,然后returnbyte[]. 有一些资源需要及时处理的“加载器”与包含“加载”数据的对象是分开的,这些数据可以在不需要处理的情况下使用。

于 2013-09-10T01:01:13.043 回答