C#“使用”语句何时最有用?

问题描述 投票:15回答:14

因此,在退出using块时,using语句会自动对正在“使用”的对象调用dispose方法,对吧?

但是什么时候有必要/有益?

例如,假设您具有此方法:

public void DoSomething()
{
    using (Font font1 = new Font("Arial", 10.0f))
    {
        // Draw some text here
    }
}

因为对象是在方法中创建的,所以这里必须要有using语句吗?当方法退出时,字体对象还是不会被丢弃?

或者在方法退出后,Dispose方法是否在其他时间运行?

例如,如果方法是这样的:

public void DoSomething()
{
    Font font1 = new Font("Arial", 10.0f);

    // Draw some text here
}

// Is everything disposed or cleared after the method has finished running?
c# using-statement
14个回答
20
投票

'using'语句在处理非托管对象(例如数据库连接)时最有用。

这样,无论代码块中发生什么,连接都会关闭并被释放。

更多讨论,请参见CodeProject上的这篇文章:http://www.codeproject.com/KB/cs/tinguusingstatement.aspx


0
投票

0
投票

0
投票

0
投票

0
投票

13
投票

没有using(或手动调用Dispose()),最终将丢弃对象,只是在确定的时间。也就是说,它可能会在两天后立即发生,或者(在某些情况下)永远不会发生。

对于诸如网络连接之类的事情,您希望在完成连接后关闭它,而不要在任何时候关闭,否则它会闲逛一个套接字。

此外,对于互斥锁,您不希望它们“在任何时候”被释放,否则很可能导致死锁。


12
投票

此:

public void DoSomething()
{
    using (Font font1 = new Font("Arial", 10.0f))
    {
        // Draw some text here
    }
}

直接映射到此:

public void DoSomething()
{
    {
        Font font1;
        try
        {
            font1 = new Font("Arial", 10.0f);
            // Draw some text here
        }
        finally
        {
            IDisposable disp = font1 as IDisposable;
            if (disp != null) disp.Dispose();
        }
    }
}

请注意finally块:即使发生异常,该对象也会被处置。还请注意额外的匿名作用域块:这意味着不仅对象被处置,而且也超出范围。

这里的另一重要事项是保证立即处置。它是确定性。如果没有using语句或类似的构造,则该对象将在方法结束时超出范围,然后可以最终被收集。然后,理想情况下将销毁该资源,以便系统可以对其进行回收。但是“最终”可能不会在一段时间内发生,并且“在理想情况下”和“将会”是完全不同的东西。

因此,“最终”并不总是足够好。诸如数据库连接,套接字,信号量/互斥量以及(在这种情况下)GDI资源之类的资源通常受到严格限制,需要立即进行清理。 using语句将确保这种情况发生。


9
投票

正在使用的构造强制执行确定性处置-即释放资源。在上面的示例中,是的,如果不使用“ using”语句,则将处置该对象,但仅当推荐的一次性模式(即,来自类终结器的资源的[[dispose)(如果适用)时)已针对相关类(在您的示例中为Font类)实现。应该注意的是,using构造只能与实现IDisposable接口的对象一起使用。该对象上存在该接口,允许使用“调用” Dispose方法。

此外,仅当垃圾收集器决定收集您的范围外的Font对象时,才会释放基础资源。 .NET编程(和大多数带有垃圾收集器的语言)中的一个关键概念是,仅仅因为对象超出范围并不意味着它已完成/释放/销毁等。相反,垃圾收集器将执行清理操作。一次确定,而不是在对象超出范围时立即确定。

最后,using语句“加入” try / finally构造以确保无论所包含的代码引发异常如何都调用Dispose。


2
投票
“使用”在需要处理资源并实现IDisposable接口时起作用。

2
投票
当方法退出时,是否会丢弃Font对象?

不,它将变为未引用,因此有资格进行垃圾回收。除非有别的东西(例如保存在另一个数据结构中的引用)保留在引用上。

或者在方法退出后,Dispose方法是否在其他时间运行?

是的,在不分配太多内存的过程中,方法退出后可能要花费相当长的时间。

垃圾回收本质上是异步的和惰性的,因此,如果内存不是太有限,它是确保释放内存的好方法;但几乎没有其他资源。


2
投票
对我来说似乎很简单。

如果一个类实现了IDisposable,那么几乎在您要创建的任何实例上调用Dispose几乎是您的问题。这是我建议使用的模式,

whenever创建了这样的实例:using (var instanceName = new DisposableClass()) { // Your code here }

很简单,很干净,它适用于除WCF代理类之外的所有其他类,这些类已损坏。对于这些,请参见http://www.iserviceoriented.com/blog/post/Indisposable+-+WCF+Gotcha+1.aspx

2
投票

0
投票
© www.soinside.com 2019 - 2024. All rights reserved.