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

时间:2011-07-20 13:22:46

标签: c# file-io scope try-catch

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

8 个答案:

答案 0 :(得分:2)

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

如果您需要处理不同的例外情况,请使用多个catch阻止单tryscottm

答案 1 :(得分:2)

你可以在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
}

答案 2 :(得分:1)

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

为什么不是你?我猜想原因是你可能会遇到异常并且不知道变量是否已初始化。所以T / C / F块结束时的状态是不确定的。如果你可以确定状态是确定的,那就没关系,IMO。

答案 3 :(得分:1)

我认为MSDN意味着可能通过声明T类型的变量可能会调用T的静态构造函数,导致异常被抛出{{1}之外阻止。

在您的示例中,我没有看到在try块之外声明变量时出现任何问题。就像scottm建议的那样。

答案 4 :(得分:1)

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

答案 5 :(得分:1)

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

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

答案 6 :(得分:1)

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

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

或者,您可以嵌套try ... catch块,这样您就可以在外部块中声明/初始化它,并在其中进一步尝试... catch块。

答案 7 :(得分:1)

我wolud建议使用using关键字,如下所示:

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

使用将保证,即使异常发生,StreamWriter将被关闭并从该块退出处理,导致using在IL中实际注入try/finally子句。如果不可能,我会认真考虑修改一个呼叫架构,如果可能的话。

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

问候。