C# 为什么这不在范围之外

C# 为什么这不在范围之外,c#,using-declaration,C#,Using Declaration,最后一个括号(底部4行)关闭using语句。这里我肯定遗漏了一些明显的东西,但是代码进行编译,传递resharper,而var消息在using语句之外使用。事实上,如果我把它放在using语句中,它就无法构建 其实从这个 “using语句确保即使在调用对象上的方法时发生异常,也会调用Dispose。通过将对象放在try块中,然后在finally块中调用Dispose,可以获得相同的结果;事实上,编译器就是这样翻译using语句的。前面的代码示例在编译时扩展为以下代码(请注意,额外的大括号用于创建

最后一个括号(底部4行)关闭using语句。这里我肯定遗漏了一些明显的东西,但是代码进行编译,传递resharper,而var消息在using语句之外使用。事实上,如果我把它放在using语句中,它就无法构建

其实从这个

“using语句确保即使在调用对象上的方法时发生异常,也会调用Dispose。通过将对象放在try块中,然后在finally块中调用Dispose,可以获得相同的结果;事实上,编译器就是这样翻译using语句的。前面的代码示例在编译时扩展为以下代码(请注意,额外的大括号用于创建对象的有限范围):

消息应该已经超出范围,并且可能已被释放

var smtp = new SmtpClient
{
    Host =smtpHost,
    Port = smtpPort,
    EnableSsl = true,
    DeliveryMethod = SmtpDeliveryMethod.Network,
    UseDefaultCredentials = false,
    Credentials = new NetworkCredential(fromAddress.Address, mailFromPassword)
};

using (var message = new MailMessage(fromAddress, toAddress)
    {
        Subject = subject,
        Body = body,
    }
)
{
    smtp.Send(message);
}
^^这是一个构造函数调用,然后是一个对象初始值设定项。下一组大括号是
using
语句的主体。请看实际using关键字的括号-它们包装了整个初始化过程。它与:

var message = new MailMessage(fromAddress, toAddress)
                {
                    Subject = subject,
                    Body = body,
                    IsBodyHtml = true
                }
最后一个括号(底部4行)关闭using语句

否,它将关闭资源获取。使用语句的形式如下:

var message = new MailMessage(fromAddress, toAddress);
message.Subject = subject;
message.Body = body;
message.IsBodyHtml = true;
embedded_语句
也可以是块:

using ( resource_acquisition ) embedded_statement
embedded_语句
可以访问在
resource_采集中创建的变量

要将其转换为代码,请执行以下操作:

using ( resource_acquisition ) 
{
    embedded_statement
}

使用
语句的一个基本示例如下:

using (var message = new MailMessage(fromAddress, toAddress) //
                    {                                        //
                        Subject = subject,                   //
                        Body = body,                         // Resource acquisition
                    }                                        //
      )                                                      //

{                                                            //
    smtp.Send(message);                                      // Embedded statement
}                                                            //
下面是如何使用
using
语句的简短示例:

using(/*declare and instantiate the instance of IDisposable here*/)
{
    // use it here.
}
var myObject = new MyObjectClass() { 
    Name = "Donald Trump" 
    Age = 71,
    Nickname = "Donnie" 
};
using (var message = new MailMessage(fromAddress, toAddress)
    {
        Subject = subject,
        Body = body,
    }
)
{
    smtp.Send(message); //IN SCOPE
}

smtp.Send(message); //THIS WOULD BE OUT OF SCOPE
这相当于:

using(var whatever = new IDisposable(parameters) {PropertyName = propertyValue})
{
    whatever.DoStuff();
}
因此,虽然代码分散在几行中,但仍然有效:

try
{
    var whatever = new IDisposable(parameters) {PropertyName = propertyValue};
    whatever.DoStuff();
}
finally
{
    whatever.Dispose();
}

您误解了您的
using
语句的结尾

考虑这个简单的例子:

using (
   var message = new MailMessage(fromAddress, toAddress)
        {
            Subject = subject,
            Body = body,
            IsBodyHtml = true
        }
)
{
    smtp.Send(message);
}
我假设你看到这个简单的例子是有效的


可以在对象初始化期间使用(=调用构造函数)

但是,当对象初始值设定项设置多个属性时,大多数开发人员更喜欢将它们拆分为新行:

var myObject = new MyObjectClass() { Name = "Donald Trump" };
对象初始值设定项也可以使用
语句在
中使用:

using(/*declare and instantiate the instance of IDisposable here*/)
{
    // use it here.
}
var myObject = new MyObjectClass() { 
    Name = "Donald Trump" 
    Age = 71,
    Nickname = "Donnie" 
};
using (var message = new MailMessage(fromAddress, toAddress)
    {
        Subject = subject,
        Body = body,
    }
)
{
    smtp.Send(message); //IN SCOPE
}

smtp.Send(message); //THIS WOULD BE OUT OF SCOPE
当一个对象初始值设定项设置多个属性时,大多数开发人员更喜欢将它们拆分为新行

using(var myObject = new MyObjectClass() { Name = "Donald Trump" })
{
    string test = myObject.Name; //IN SCOPE
}

string test2 = myObject.Name; //OUT OF SCOPE

请注意,在我的所有示例中,
使用
块的主体从未改变

因此,当我们现在来看您的示例时:

using(var myObject = new MyObjectClass() { 
    Name = "Donald Trump" 
    Age = 71,
    Nickname = "Donnie" 
})
{
    string test = myObject.Name; //IN SCOPE
}

string test2 = myObject.Name; //OUT OF SCOPE
如果我将对象初始值设定项转换为单行语句,可能更容易理解:

using(/*declare and instantiate the instance of IDisposable here*/)
{
    // use it here.
}
var myObject = new MyObjectClass() { 
    Name = "Donald Trump" 
    Age = 71,
    Nickname = "Donnie" 
};
using (var message = new MailMessage(fromAddress, toAddress)
    {
        Subject = subject,
        Body = body,
    }
)
{
    smtp.Send(message); //IN SCOPE
}

smtp.Send(message); //THIS WOULD BE OUT OF SCOPE

“最后一个括号(底部4行)关闭using语句。”不,它没有。它关闭声明,然后实际语句块开始(包含单个语句
smtp.Send
)。
smtp.Send(message)
位于
using
块内。
{
在此之前,只需初始化
MailMessage
。我已经重新格式化了您的代码,以明确上面的注释:)using声明中声明的变量仍然在范围内,事实上,您使用它的方式实际上是推荐的方法,从-
来看,实例化obje通常更好ct在using语句中,并将其范围限制为using块。