什么时候C#"使用"语句最有用?

Joh*_*ski 14 c# using-statement

因此,当退出using块时,using语句会自动调用正在"使用"的对象上的dispose方法,对吗?

但这何时有必要/有益?

例如,假设您有这种方法:

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

是否有必要在此处使用using语句,因为该对象是在方法中创建的?当方法退出时,不会丢弃Font对象?

或者在方法退出后,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?
Run Code Online (Sandbox Code Playgroud)

Jef*_*itz 19

使用非托管对象(如数据库连接)时,"using"语句最有用.

通过这种方式,无论代码块中发生什么,连接都被关闭和处理.

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


Chr*_*ung 13

如果没有using(或手动调用Dispose()),对象最终将被处理掉,而不是在确定的时间.也就是说,它可以在两天内立即发生,或者(在某些情况下)永远不会发生.

对于像网络连接这样的东西,你希望连接完成时关闭,而不是"随时"关闭,否则它会在占用套接字时闲置.

此外,对于像互斥锁这样的东西,你不希望"随时"释放它们,否则可能会导致死锁.


Joe*_*orn 11

这个:

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

直接映射到这个:

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

注意finally块:即使发生异常,也会处理对象.还要注意额外的匿名范围块:它意味着不仅要处理对象,而且它也超出了范围.

另一个重要的事情是保证立即处置.这是确定性的.如果没有using语句或类似的构造,该对象在方法结束时仍会超出范围,最终可能会被收集.理想情况下,资源将被销毁,以便系统可以回收它.但"最终"可能不会发生一段时间,"理想上"和"意志"是非常不同的事情.

因此,"最终"并不总是足够好. 数据库连接,套接字,信号量/互斥量和(在这种情况下)GDI资源等资源通常受到严格限制,需要立即清理.using语句将确保发生这种情况.


Pet*_*yer 9

使用构造强制执行确定性处置 - 即释放资源.在上面的示例中,是的,如果您不使用"using"语句,则将处置该对象,但仅当已实施推荐的一次性模式(即,从类终结器处理资源,如果适用)时对于有问题的类(在您的示例中,为Font类).应该注意,using构造只能用于实现IDisposable接口的对象.在对象上存在该接口,允许使用"调用"该Dispose方法.

此外,仅当垃圾收集器决定收集超出范围的Font对象时,才会释放底层资源..Net编程中的一个关键概念(以及大多数带有垃圾收集器的语言)只是因为一个对象超出范围并不意味着它被最终确定/释放/销毁等等.相反,垃圾收集器将执行清理 - 它确定的时间 - 当对象超出范围时不立即.

最后,using语句"bakes in"一个try/finally结构,以确保调用Dispose而不管包含的代码是否抛出异常.