我如何知道使用“using”的最佳位置?

发布于 2024-07-16 06:19:52 字数 276 浏览 6 评论 0原文

我对 C# 有点陌生,更习惯脚本语言。 我喜欢“使用”的想法,你实例化一个对象,然后只要你需要它,你就可以在它的范围内进行操作,然后当它完成它的目的时,让它自行处理。

但是,这对我来说并不自然。 当人们向我展示使用它的示例时,我认为它是完成工作的好工具,但我从未想过在自己的编程中使用它解决问题。

我如何识别使用 using 的好地方以及如何将它与 try-catch 块结合使用。 它们是否进入块内部,或者您通常希望将 using 语句包含在 try 块内?

I'm somewhat new to c#, more accustomed to scripting languages. I like the idea of 'using', you instantiate an object, and then you operate within its scope as long as you need it, then you let it dispose of itself when it's done its purpose.

But, it's not natural for me. When people show me examples using it, I recognize it as a good tool for the job, but it never occurs to me to solve problems with it in my own programming.

How can I recognize good places to use using and how do I use it in conjunction with try-catch blocks. Do they go inside the block, or do you usually want to enclose a using statement within a try block?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

过潦 2024-07-23 06:19:52

using 只能与实现 IDisposable 的类型一起使用; 它保证即使发生错误也会调用 Dispose() 方法。

此代码:

using (MyDisposableType x = new MyDisposableType())
{  
    // use x
}

相当于:

MyDisposableType x = new MyDisposableType();
try
{  
    // use x
}
finally 
{ 
    x.Dispose(); 
}

using can only be used with types that implement IDisposable; it guarantees that the Dispose() method will be called even if an error occurs.

This code:

using (MyDisposableType x = new MyDisposableType())
{  
    // use x
}

is equivalent to this:

MyDisposableType x = new MyDisposableType();
try
{  
    // use x
}
finally 
{ 
    x.Dispose(); 
}
今天小雨转甜 2024-07-23 06:19:52

我很少编写 try/catch 块 - 大多数异常都会被抛出到(接近)堆栈顶部。 如果我确实需要一个try/catch块,我不确定将其放在using语句内部与外部是否特别一致。 这实际上取决于您是否希望在运行异常处理代码之前或之后释放资源。

如果您询问何时,您应该编写using语句 - 任何时候您“拥有”一个实现IDisposable的对象(直接或间接通过继承)并控制其生命周期。 这通常是一个使用非托管资源(如文件句柄或网络连接)的对象。 它并不总是非常明显,但你可以通过经验来学习。 几乎任何与 IO 相关的东西都是一次性的,Windows 句柄(用于字体等)也类似。

I rarely write try/catch blocks - most exceptions get thrown up to (near) the top of the stack. If I do need a try/catch block, I'm not sure I'm particularly consistent between putting it inside the using statement vs outside. It really depends on whether you want the resource to be disposed before of after your exception handling code is run.

If you're asking about when you should be writing using statements - any time you "own" an object which implements IDisposable (either directly or indirectly through inheritance) and control its lifetime. That's usually an object which uses an unmanaged resource like a file handle or network connection. It's not always hugely obvious, but you learn through experience. Almost anything to do with IO will be disposable, and Windows handles (for fonts etc) are similar.

天暗了我发光 2024-07-23 06:19:52

我过去常常将其视为“每次类型实现 IDisposable 时都使用它,并且您将不再需要此特定实例”。

I use to think of it as "Use it every time when type implements IDisposable and you you're not goinng to need this particular instance any more".

简单爱 2024-07-23 06:19:52

如果您想知道如何在您自己的设计中创造性地使用它,请查看您自己的一些代码,以了解在退出封闭块之前绝对必须执行特定代码位的情况。 在这些情况下,try/finallyusing 可以为您提供帮助。

特别是,如果您尝试通过捕获所有异常来实现此目的,那么您确实必须更改为 try/finallyusing

如果该模式出现多次,您可以创建一个实现 IDisposable 的类来捕获该模式,并允许您使用 using 语句调用该模式。 但如果您遇到的特定情况似乎是一次性的,那么只需使用 try/finally 即可。

两者非常相似,实际上 - using 是根据 try/finally 指定的,但即使我们只有 using< /code>,我们可以自己构建 try/finally

public class DisposeAnything : IDisposable
{
    public Action Disposer;

    public void Dispose()
    {
        Disposer();
    }
}

现在你可以说:

using (new DisposeAnything 
      {
          Disposer = () => File.Delete(tempFileName) 
      })
{
    // blah
}

这与以下内容相同:

try
{
    // blah
}
finally
{
    File.Delete(tempFileName);
}

只需将其视为执行某些代码的一种方法离开范围后。

If you want to know how to creatively use it within your own designs, look through some of your own code for situations where a particular bit of code absolutely must execute before the enclosing block is exited. These are the situations where try/finally or using can help you.

In particular, if you've tried to achieve this by catching all exceptions, then you really must change to try/finally or using instead.

If the pattern occurs several times, you could create a class that implements IDisposable in order to capture the pattern, and allowing you to invoke the pattern with the using statement. But if you have a specific case that appears to be a one-off, then just use try/finally.

The two are very similar, really - using is specified in terms of try/finally, but even if we only had using, we could build try/finally ourselves:

public class DisposeAnything : IDisposable
{
    public Action Disposer;

    public void Dispose()
    {
        Disposer();
    }
}

Now you could say:

using (new DisposeAnything 
      {
          Disposer = () => File.Delete(tempFileName) 
      })
{
    // blah
}

Which is the same as:

try
{
    // blah
}
finally
{
    File.Delete(tempFileName);
}

Just think of it as a way to get some code to execute upon leaving a scope.

写下不归期 2024-07-23 06:19:52

Mitch 说的是,另外..

您可以在 try..catch 块外部或内部使用 using 语句,这实际上取决于您想要实现的目标,即您是否合理地期望在使用您所使用的特定对象时抛出异常。例如,计划从中恢复。

出于同样的原因,如果需要,您还可以在finally 块中释放一个实现IDisposable 的对象。

WHat Mitch said, plus..

You can use the using statement outside or inside a try..catch block it really would depend on what you are trying to achieve i.e. whether you reasonably expect something to throw an exception whilst using a particular object which you plan to recover from, for example.

By the same token, you could also Dispose of an object which implements IDisposable in a finally block if you needed to.

习ぎ惯性依靠 2024-07-23 06:19:52

您可以将 using 包含在 try/catch 块内,也可以将 try/catch 块包含在 using 内。

using 很好的一种情况是当您使用 DBConnection 和 DBCommands 执行数据库操作时:

using (SqlConnection conn = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand(sql, conn))
{
  // do something here
}

现在,当您离开 using 块时,您的命令将被释放并关闭连接。

You can enclose a using inside a try/catch block and you can enclose a try/catch block inside a using.

One situation where using is nice is when you are doing database operations using DBConnection and DBCommands:

using (SqlConnection conn = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand(sql, conn))
{
  // do something here
}

Now when you leave the using blocks your command is disposed and the connection is closed.

风吹雨成花 2024-07-23 06:19:52

米奇说的是对的。 因此,using 的主要用途是确保 IDisposable 对象得到处置,不必编写 try/catch 或 try/finally 语句。

现在,您可能也会对更高级的用途感兴趣。 当您使用 using 语句时,编译器会生成一个 try/finally,并且还会在它生成的 finally 内部为您生成对 Dispose() 的调用。 您可以使用此 Dispose() 方法作为“钩子”来执行您想要的任何操作...不必与释放资源相关。

例如,Jeffrey Richter 在他编写的计时器对象中使用了它。 你可以用它做这样的事情(仅概念性的):

using(var x = new Timer())
{
  // Do the operation you want timed
}

// Now, the timer has been stopped, because the 
// compiler-generated call to Dispose() has already 
// occurred, and Jeffrey uses Dispose() to stop 
// the timer.

What Mitch said is right. So the main use of using is to ensure that IDisposable objects get disposed of, without having to code a try/catch or try/finally statement.

Now, there's a more advanced use you might find interesting as well. When you use a using statement, the compiler generates a try/finally, and it also generates a call to Dispose() for you inside of the finally that it generates. You can use this Dispose() method as a "hook" to do anything you want ... doesn't have to be related to releasing resources.

For example, Jeffrey Richter uses this in a timer object he wrote. You can do something like this with it (conceptual only):

using(var x = new Timer())
{
  // Do the operation you want timed
}

// Now, the timer has been stopped, because the 
// compiler-generated call to Dispose() has already 
// occurred, and Jeffrey uses Dispose() to stop 
// the timer.
止于盛夏 2024-07-23 06:19:52

如果一个类实现了 IDisposable,这可能是有充分理由的。 因此,任何实现 IDisposable 的类都应该被释放。

If a class implements IDisposable, it's probably for good reason. So any class that implements IDisposable should be disposed.

舂唻埖巳落 2024-07-23 06:19:52

鉴于它就是所谓的“语法糖”,并且将生成与 try/finally dispose 构造相同的 IL,它实际上只是“简化”此类代码的一种好方法。

我喜欢用它来简化大量使用一次性对象的代码部分,即访问文件和图形对象等资源,并且我想确保我不会忘记处理资源对象的处置。

Given that it is what is known as "syntactic sugar" and will produce the same IL as a try/finally dispose construct, it is really just a nice way of "short-handing" such code.

I like to use it to simplify sections of code where disposable objects are used a lot i.e. access to resources such as files and graphics objects and I want to make sure that I don't forget to handle the disposing of the resource object.

轻许诺言 2024-07-23 06:19:52

当您需要确定性对象处置时,请使用using。 例如,如果您打开一个文件,该文件将被锁定。 您通常会希望尽快关闭该文件,以便其他程序可以访问它。 如果你不使用 using 并写成这样:

System.IO.FileStream writeStream = new System.IO.FileStream( fileName, System.IO.FileMode.OpenOrCreate ) );
System.IO.BinaryWriter writer = new System.IO.BinaryWriter( writeStream ) );
//do smth 

并且在“do smth”期间发生异常,你不知道对文件操作的对象何时实际被释放并且文件被关闭。 使用using,您可以确定一旦离开using语句块 - 无论是直接还是通过异常,usinging语句中的对象都是通过调用 IDisposable::Dispose 进行处置:

using( System.IO.FileStream writeStream = new System.IO.FileStream( fileName, System.IO.FileMode.OpenOrCreate ) ) {
    using( System.IO.BinaryWriter writer = new System.IO.BinaryWriter( writeStream ) ) {
        //do stmth
    }
}

Use using when you need deterministic object disposal. For example, if you open a file, the file is locked. You will often want the file to be closed as soon as possible so that other programs could access it. If you don't use using and write smth like:

System.IO.FileStream writeStream = new System.IO.FileStream( fileName, System.IO.FileMode.OpenOrCreate ) );
System.IO.BinaryWriter writer = new System.IO.BinaryWriter( writeStream ) );
//do smth 

and an exception occurs during "do smth" you don't know when the objects operating on a file are actually disposed and file is closed. With using you know for sure that once you've left the using statement block - either directly or via exception the object in the useing statement is disposed by calling IDisposable::Dispose:

using( System.IO.FileStream writeStream = new System.IO.FileStream( fileName, System.IO.FileMode.OpenOrCreate ) ) {
    using( System.IO.BinaryWriter writer = new System.IO.BinaryWriter( writeStream ) ) {
        //do stmth
    }
}
或十年 2024-07-23 06:19:52

我注意到,当已知 Dispose 方法确实会引起注意时,程序员就不会费心调用它,因为它似乎毫无意义。 但是,如果该对象实现了 IDisposable (希望)是有原因的,并且该对象的未来版本实际上可能在 Dispose 方法中包含代码 - 因此请始终调用它。

I've noticed that when the Dispose method is known to do notice, so programmers don't bother calling it as it seems pointless. However, if the object implements IDisposable it's (hopefully) for a reason and future versions of that object may actually have code in the Dispose method - so always call it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文