我应该如何安全地初始化然后在不同的try块中使用一个变量

本文关键字:try 变量 一个 安全 何安全 初始化 我应该 然后 | 更新日期: 2023-09-27 18:02:58

所以,我需要使用StreamWriter类创建一个文件,写入它,然后关闭它,我想把所有潜在的不可执行的操作在try块;由于文件创建和写入操作将在不同的尝试块中,我不能在一个尝试块中初始化StreamWriter变量(创建文件),然后在另一个尝试块中使用它。我想我可以在try块外声明StreamWriter变量并将其设置为null,然后在try块中初始化它,但MSDN说"当在try块内,只初始化在其中声明的变量;否则,在块执行完成之前可能会发生异常。安全声明、初始化、使用文件流变量(或任何变量)然后销毁它的最佳实践是什么?也许我应该使用一些东西而不是StreamWriter?另外,如果没有在try块中声明变量,为什么不应该在try块中初始化它呢?谢谢。

我应该如何安全地初始化然后在不同的try块中使用一个变量

您可以在try块之外声明它,只是要确保处理正确的处理。

StreamWriter sw = null;
try
{
    sw = new StreamWriter(File.Open("test.txt", FileMode.OpenOrCreate));
    sw.Write("Some text.");
}
catch
{
    // Whatever you want to catch
}
finally
{
    if(sw != null)
        sw.Dispose();
    sw = null;  
}

try
{
    sw = new StreamWriter(File.Open("otherfile.txt", FileMode.OpenOrCreate));
}
catch
{
    // Whatever you want to catch
}
finally
{
    if(sw != null)
        sw.Dispose();
    sw = null;  
}

虽然,我不建议在多个try块中使用相同的变量,但这样做会获得什么?

为什么不这样呢:

try
{
    using(var sw = new StreamWriter(File.Open("text.txt", FileMode.OpenOrCreate)))
    {
        sw.Write("some text");
    }
}
catch
{
    // handle exception
}

try
{
    using(var sw = new StreamWriter(File.Open("otherfile.txt", FileMode.OpenOrCreate)))
    {
        sw.Write("some other text");
    }
}
catch
{
    // handle exception
}

在类级别定义的StreamWriter不是方法吗?如果可能的话,我建议使用单个try块。

如果您需要处理不同的异常,请按照scottm

的建议为单个try使用多个catch块。

StreamWriter的生命周期应该由using块来管理。

如果你想从两个try块中访问它,那么将变量声明移到两个try块之外的本能是正确的。MSFT指南只是试图给你留下深刻的印象,在这种情况下,如果你有可能的异常发生在声明之后,但在try块之前,他们不会被捕获,但初始化一个变量为null不会抛出异常,如果你不做任何事情,你是好的。(如果你真的担心它,你可以创建一个try/catch封装变量声明和其他try块)我个人不喜欢很多try/catch,但这是另一天的布道…

如果您想在两个不同的try块中访问一个变量,则需要在两个块之外(以某种方式)声明它。这就是简单的作用域控制。

为什么不呢?我猜原因是您可能会遇到异常,而不知道变量是否已初始化。所以在T/C/F块末端的状态是不确定的。如果你能确定状态是确定的,那么它是OK的,IMO。

我认为MSDN的意思是有可能通过声明T类型的变量来调用T的静态构造函数,从而导致在try块之外抛出异常。

在您的示例中,我没有看到在try块之外声明变量的任何问题。就照scottm的建议去做吧。

在声明中将变量设置为null与初始化它相同。它只是不包含对任何真实对象的有效引用,但您可以对此进行测试。你不能测试未初始化的变量:如果你有一个可能导致使用未初始化变量的路径,你会得到编译错误。

在try…Catch块,但不要初始化它。在块内进行初始化。你提到的MSDN文章似乎暗示这不是一个好主意,但我不明白为什么。

声明不会失败,但初始化可能失败。

或者,您可以嵌套try…Catch块,所以你可以在外部块中声明/初始化它,然后进一步尝试…捕获其中的块。

我建议使用using关键字,像这样:

  try {
  using(StreamWriter sw = new (...)) {
     //use stream here
  }
  }
  catch(Exception ex) {}

使用将被保证,通过设计,StreamWriter将被关闭,并在退出该块时处理,即使发生异常,因为using实际上在IL中注入try/finally子句。如果不可能这样做,我会认真考虑修改调用的体系结构,如果可能的话。

IO流的一般规则:在尽可能短的时间内打开/使用/关闭

问候。