2017-09-25 123 views
-2
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); 
} 

最后一个括号(底部4行)关闭using语句。我必须在这里忽略一些明显的东西,但是代码编译,通过resharper,但var消息在using语句之外使用。事实上,如果我把它放在using语句中,它就无法构建。为什么这不超出范围

其实从这个https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-statement

“using语句确保处置是即使当你调用对象的方法发生异常调用。您可以通过将对象try块内达到同样的效果然后在finally块中调用Dispose;实际上,这就是编译器翻译using语句的方式。前面的代码示例在编译时展开为以下代码(请注意额外的大括号来为对象创建有限的作用域):“

消息应该已经超出范围并可能处置。

+7

“最后的括号(4线从底部)关闭使用声明。“不,它没有。它关闭声明,然后开始实际的语句块(包含单个语句“smtp.Send”)。 –

+4

'smtp.Send(message)'位于'using'块中。之前的'{}'只是MailMessage的初始化。 –

+0

我已将代码重新格式化,以使上述评论清楚:) –

回答

4

最后括号(从下4行)关闭using语句

没有,它会关闭资源获取。使用语句有如下形式:

using (resource_acquisition) embedded_statement 

embedded_statement也可以是块:

using (resource_acquisition) 
{ 
    embedded_statement 
} 

embedded_statement访问的resource_acquisition创建的变量。

要翻译,为您的代码:

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

{               // 
    smtp.Send(message);          // Embedded statement 
}               // 
0
var message = new MailMessage(fromAddress, toAddress) 
       { 
        Subject = subject, 
        Body = body, 
        IsBodyHtml = true 
       } 

^^这是一个构造函数调用,然后是一个对象初始化器。 下一步一套大括号是using声明的正文。查看实际使用关键字的括号 - 它们包含了整个初始化过程。这是一样的:

var message = new MailMessage(fromAddress, toAddress); 
message.Subject = subject; 
message.Body = body; 
message.IsBodyHtml = true; 
2

using声明的一个基本的例子是这样的:

using(/*declare and instantiate the instance of IDisposable here*/) 
{ 
    // use it here. 
} 

这里是你如何使用using声明较短例如:

using(var whatever = new IDisposable(parameters) {PropertyName = propertyValue}) 
{ 
    whatever.DoStuff(); 
} 

这相当于:

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

所以,尽管在几行传播出去,你的代码仍然有效:

using (
    var message = new MailMessage(fromAddress, toAddress) 
     { 
      Subject = subject, 
      Body = body, 
      IsBodyHtml = true 
     } 
) 
{ 
    smtp.Send(message); 
} 
0

你误会您的using语句结束。

考虑一个简单的例子:

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

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

我假设你看到这个简单的例子是有效的。


Object initializers可以将对象(=调用构造)的初始化期间使用。

var myObject = new MyObjectClass() { Name = "Donald Trump" }; 

但是当对象初始设置多个属性,大多数开发人员更喜欢他们在新的行拆分:

var myObject = new MyObjectClass() { 
    Name = "Donald Trump" 
    Age = 71, 
    Nickname = "Donnie" 
}; 

对象初始化,也可以在using语句中使用:

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块的已经从未改变

所以,当我们现在就来看看你的例子:

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 message = new MailMessage(fromAddress, toAddress) { Subject = subject, Body = body }) 
{ 
    smtp.Send(message); //IN SCOPE 
} 

smtp.Send(message); //THIS WOULD BE OUT OF SCOPE 
相关问题