11

我正在返回我在 using 语句内的 using 语句中创建的变量(听起来很有趣):

public DataTable foo ()
{
    using (DataTable properties = new DataTable())
    {
       // do something
       return properties;
    }
}

这会处理属性变量吗?

这样做后仍然收到此警告:

警告 34 CA2000:Microsoft.Reliability:在方法“test.test”中,在对对象“属性”的所有引用超出范围之前调用 System.IDisposable.Dispose。

有任何想法吗?

谢谢

4

7 回答 7

12

如果要返回它,则不能将其包装在using语句中,因为一旦离开大括号,它就会超出范围并被丢弃。

您必须像这样实例化它:

public DataTable Foo() 
{ 
    DataTable properties = new DataTable();
    return properties; 
} 

Dispose()稍后再调用它。

于 2010-05-12T20:55:02.520 回答
10

是的,它会处理它 - 然后返回它。这几乎总是一件坏事。

事实上,对于DataTable,Dispose几乎从不做任何事情(例外是如果它在某处被远程,IIRC),但这仍然是一个普遍的坏主意。通常,您应该将已处理的对象视为不可用。

于 2010-05-12T20:56:58.933 回答
7

据说,这是创建一次性对象的工厂方法的模式。但是,我仍然看到代码分析也抱怨这个:

        Wrapper tempWrapper = null;
        Wrapper wrapper = null;

        try
        {
            tempWrapper = new Wrapper(callback);
            Initialize(tempWrapper);

            wrapper = tempWrapper;
            tempWrapper = null;
        }
        finally
        {
            if (tempWrapper != null)
                tempWrapper.Dispose();
        }

        return wrapper;

这应该保证如果初始化失败,对象被正确释放,但如果一切成功,则从方法返回一个未释放的实例。

MSDN 文章:CA2000:在失去范围之前处置对象

于 2010-05-12T21:02:05.467 回答
3

是的。为什么要using在不希望在代码块末尾处理的内容上使用关键字?

关键字的目的using是处置对象。

http://msdn.microsoft.com/en-us/library/yh598w02.aspx

于 2010-05-12T20:56:38.270 回答
2

using 块的要点是为值/对象创建人工范围。当 using 块完成时,该对象将被清理,因为它不再需要。如果您真的想返回您正在创建的对象,那么您不想使用 using。

这将工作得很好。

public DataTable foo ()
{
    DataTable properties = new DataTable();
    // do something
    return properties;
}
于 2010-05-12T20:59:28.703 回答
1

您使用 using 关键字的代码扩展为:

{
    DataTable properties = new DataTable();
    try
    {
        //do something
        return properties;
    }
    finally
    {
        if(properties != null)
        {
            ((IDisposable)properties).Dispose();
        }
    }
}

您的变量是按照使用方式的性质处理的。如果您希望能够返回属性,请不要将其包装在 using 块中。

于 2010-05-12T20:59:44.620 回答
0

其他响应是正确的:一旦您退出 using 块,您的对象就会被释放。using 块非常适合确保及时释放对象,因此如果您不想依赖函数的使用者记住稍后释放对象,您可以尝试以下操作:

public void UsingDataContext (Action<DataContext> action)
{
    using (DataContext ctx = new DataContext())
    {
       action(ctx)
    }
}

这样你就可以这样说:

var user = GetNewUserInfo();
UsingDataContext(c => c.UserSet.Add(user));
于 2010-05-12T21:35:41.507 回答