代码之家  ›  专栏  ›  技术社区  ›  danieltalsky

我怎么知道“使用”的最佳位置?

  •  7
  • danieltalsky  · 技术社区  · 16 年前

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

    但是,这对我来说并不自然。当人们向我展示使用它的例子时,我认识到它是一个很好的工作工具,但我从未在自己的编程中用它来解决问题。

    我怎样才能认出好地方 using 以及如何将它与try-catch块结合使用。它们是进入块内,还是通常希望将using语句包含在try块内?

    11 回复  |  直到 16 年前
        1
  •  9
  •   Jon Skeet    16 年前

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

    如果你问 什么时候? 你应该写信 使用 语句-任何时候你“拥有”一个实现 IDisposable (通过继承直接或间接)并控制其寿命。这通常是一个使用非托管资源(如文件句柄或网络连接)的对象。这并不总是显而易见的,但你是通过经验来学习的。几乎 任何东西 与IO相关的操作是一次性的,而Windows句柄(用于字体等)是相似的。

        2
  •  18
  •   Mitch Wheat    16 年前

    using 只能用于实现 IDisposable ;它保证 Dispose() 即使发生错误,也将调用方法。

    此代码:

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

    相当于:

    MyDisposableType x = new MyDisposableType();
    try
    {  
        // use x
    }
    finally 
    { 
        x.Dispose(); 
    }
    
        3
  •  3
  •   Dmitry Ornatsky    16 年前

    我常常认为它是“每次类型实现IDisposable时都使用它,而您不再需要这个特定的实例”。

        4
  •  2
  •   Daniel Earwicker    16 年前

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

    尤其是,如果您试图通过捕获所有异常来实现这一点,那么您真的必须改为 尝试 / 最后 使用 相反。

    如果模式出现多次,则可以创建一个实现 IDisposable 为了捕获模式,并允许您使用 使用 语句。但是如果你有一个特定的案例看起来是一次性的,那么就使用 尝试 / 最后 .

    这两个非常相似,真的- 使用 是根据 尝试 / 最后 但是即使我们 使用 我们可以建造 尝试 / 最后 我们自己:

    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);
    }
    

    把它当作一种在离开作用域时让一些代码执行的方法。

        5
  •  1
  •   RobS    16 年前

    米奇说的,还有……

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

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

        6
  •  1
  •   Rune Grimstad    16 年前

    您可以在try/catch块中包含一个using,也可以在using中包含一个try/catch块。

    使用的一个好处是,当使用dbconnection和dbcommands执行数据库操作时:

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

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

        7
  •  1
  •   Charlie Flowers    16 年前

    米奇说的是对的。因此,使用的主要用途是确保IDisposable对象得到处理, 没有 必须对try/catch或try/finally语句进行编码。

    现在,还有一个更高级的用法,您可能会发现它也很有趣。当使用using语句时,编译器会生成一个try/finally,并在它生成的finally中为您生成一个dispose()调用。您可以使用这个dispose()方法作为“hook”来执行您想要的任何操作…不必与释放资源相关。

    例如,JeffreyRichter在他编写的计时器对象中使用了这个。您可以使用它执行类似的操作(仅限概念上的操作):

    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.
    
        8
  •  1
  •   Dave Van den Eynde    16 年前

    如果一个类实现IDisposable,这可能是有原因的。因此,应释放实现IDisposable的任何类。

        9
  •  1
  •   Gordon Mackie JoanMiro    16 年前

    考虑到它是所谓的“语法糖”,并且将产生与try/finally dispose构造相同的IL,它实际上只是一种“短处理”此类代码的好方法。

    我喜欢使用它来简化代码中使用一次性对象较多的部分,即访问文件和图形对象等资源,我希望确保不会忘记处理资源对象的处理。

        10
  •  1
  •   sharptooth    16 年前

    使用 使用 当需要确定性对象处理时。例如,如果打开一个文件,该文件将被锁定。您通常希望尽快关闭该文件,以便其他程序可以访问它。如果你不使用 使用 写下smth,就像:

    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”期间会发生一个异常,您不知道在文件上操作的对象何时被实际释放,文件何时被关闭。用 使用 你知道一旦你离开 使用 语句块-直接或通过异常 使用 通过调用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
        }
    }
    
        11
  •  0
  •   dommer    16 年前

    我注意到,当Dispose方法被认为需要注意时,程序员就不必费心调用它了,因为它似乎毫无意义。但是,如果对象实现了IDisposable,那么(希望)出于某种原因,该对象的未来版本可能实际在Dispose方法中有代码,因此始终调用它。