简体   繁体   English

scope 在 c# 中使用 try/catch 包围“新”语句时

[英]scope when surrounding 'new' statement with try/catch in c#

This is a question of what the 'best practice' is for declaring new variables, and I've seen this situation a few times now.这是一个关于什么是声明新变量的“最佳实践”的问题,我现在已经多次看到这种情况了。 I have a class whose constructor reads a config file, eg:我有一个 class 的构造函数读取配置文件,例如:

ConfigMgr config = new ConfigMgr(args[0]);

Of course, if you run the console app without that argument, an exception results.当然,如果您在没有该参数的情况下运行控制台应用程序,则会导致异常。 If I surround that line with a try/catch as follows, I get the error 'The name 'config' does not exist in the current context'.如果我按如下方式用 try/catch 包围该行,则会收到错误“当前上下文中不存在名称 'config'”。 Understandable.可以理解。

try
{
    ConfigMgr config = new ConfigMgr(args[0]);
}
catch
{
    Console.WriteLine("Config file not specified or incorrect in format.  Exiting.");
    Console.ReadLine();
}

// Defaults
string aucomposingfile = config.getValue("aucomposingfile");
string nzcomposingfile = config.getValue("nzcomposingfile");
...etc

I could separate out the part that requires the argument in the constructor - do the new ConfigMgr part outside the try/catch block, then do something like config.LoadFile() in the try/catch.我可以在构造函数中分离出需要参数的部分——在 try/catch 块之外执行新的 ConfigMgr 部分,然后在 try/catch 中执行类似 config.LoadFile() 的操作。 But I can't imagine that's what those in the know do.但我无法想象那些知情人士会这样做。

Any thoughts?有什么想法吗?

Thanks!谢谢!

There is no reason why you cannot do this:你没有理由不能这样做:

ConfigMgr config = null;
try
{
    config = new ConfigMgr(args[0]);
}
catch ( /* catch a specific exception!! */ ) 
{
    //log it:
    Console.WriteLine("Config file not specified or incorrect in format.  Exiting.");

    //escape from here, because you don't want to continue:
    throw;    
}

string aucomposingfile = config.getValue("aucomposingfile");
string nzcomposingfile = config.getValue("nzcomposingfile");

Of course the arguably more correct way may be to check the command line arguments before attempting to use them, and throw a specific exception if they don't meet your requirements - you depend on them, so verify them first.当然,可以说更正确的方法可能是在尝试使用它们之前检查命令行 arguments,如果它们不符合您的要求,则抛出一个特定的异常 - 您依赖它们,所以首先验证它们。 This has a better code flow than just trying to use them and catching an exception.这比仅仅尝试使用它们并捕获异常具有更好的代码流。 This way your catch block becomes more focused on problems more specific to the config file, rather than handling issues with the command line arguments as well.这样,您的catch块将更加关注配置文件更具体的问题,而不是使用命令行 arguments 来处理问题。

If you need to access a variable in more than just a try block, you need to declare and initialize the variable before the block.如果您需要访问的不仅仅是try块中的变量,则需要在该块之前声明初始化该变量。 Simply declaring and initializing to null is sufficient.只需声明并初始化为 null 就足够了。

Foo foo = null;
try 
{
    foo = DoSomethingToGetFoo();
}
catch (SpecificException ex)
{
    // do whatever, foo is accessible but may require null-checking
}
finally 
{
    // ditto 
}

// still accessible

Obviously, declaring the variable in an outer scope is necessary if you wish to access it elsewhere.显然,如果您希望在其他地方访问它,则必须在外部 scope 中声明该变量。 But initializing is also necessary, as the C# compiler will require proof that a variable has been initialized prior to allowing you to use it.但初始化也是必要的,因为 C# 编译器需要证明变量在允许您使用之前已经初始化。 If the "standard" initializer is in the scope of the try , the compiler cannot guarantee that it will have occured prior to being used later.如果“标准”初始值设定项位于try的 scope 中,则编译器不能保证它会在以后使用之前发生。

For your own code, you can decide if everything you need to do with a variable can be contained within the try .对于您自己的代码,您可以决定是否需要对变量执行的所有操作都包含在try中。 If so, obviously limit its scope to that block.如果是这样,显然将其 scope 限制在该块中。 But in some situations, you need a broader scope.但在某些情况下,您需要更宽的 scope。 (See: the expansion of using for IDisposable objects.) (参见: using IDisposable对象的扩展。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM