如果我使用对象初始使用块在我得到不处置的对象正确code分析警告:
If I use object initializers in using-block I get Code Analysis warning about not disposing the object properly:
CA2000:Microsoft.Reliability:在方法ReCaptcha.CreateReCaptcha(此HtmlHelper的,串,字符串),对象'&所述;> G_的 initLocal0'没有设置沿所有的异常路径。呼叫System.IDisposable.Dispose对象。<>先按g 的_initLocal0的所有引用之前超出范围
CA2000 : Microsoft.Reliability : In method 'ReCaptcha.CreateReCaptcha(this HtmlHelper, string, string)', object '<>g_initLocal0' is not disposed along all exception paths. Call System.IDisposable.Dispose on object '<>g_initLocal0' before all references to it are out of scope.
下面是code:
using (var control = new ReCaptchaControl()
{
ID = id,
Theme = theme,
SkipRecaptcha = false
})
{
// Do something here
}
如果我不使用对象初始化,code分析是幸福的:
If I do not use object initializers, Code Analysis is happy:
using (var control = new ReCaptchaControl())
{
control.ID = id;
control.Theme = theme;
control.SkipRecaptcha = false;
// Do something here
}
这两个code块之间的区别是什么?我以为他们会产生相同的IL。或者,这是在code分析引擎中的错误?
What is the difference between those two code blocks? I thought that they would result in same IL. Or is this a bug in the code analysis engine?
没有,有一个区别。
这是初始化对象只分配给的所有属性设置完成后,该变量的。换句话说,这样的:
An object initializer only assigns to the variable after all the properties have been set. In other words, this:
Foo x = new Foo { Bar = "Baz" };
等同于:
Foo tmp = new Foo();
tmp.Bar = "Baz";
Foo x = tmp;
这意味着,如果物业制定者之一,你的情况引发了异常,该对象将不进行处理。
That means that if one of the property setters threw an exception in your case, the object wouldn't be disposed.
编辑:我想...试试这个:
As I thought... try this:
using System;
public class ThrowingDisposable : IDisposable
{
public string Name { get; set; }
public string Bang { set { throw new Exception(); } }
public ThrowingDisposable()
{
Console.WriteLine("Creating");
}
public void Dispose()
{
Console.WriteLine("Disposing {0}", Name);
}
}
class Test
{
static void Main()
{
PropertiesInUsingBlock();
WithObjectInitializer();
}
static void PropertiesInUsingBlock()
{
try
{
using (var x = new ThrowingDisposable())
{
x.Name = "In using block";
x.Bang = "Ouch";
}
}
catch (Exception)
{
Console.WriteLine("Caught exception");
}
}
static void WithObjectInitializer()
{
try
{
using (var x = new ThrowingDisposable
{
Name = "Object initializer",
Bang = "Ouch"
})
{
// Nothing
}
}
catch (Exception)
{
Console.WriteLine("Caught exception");
}
}
}
输出:
Creating
Disposing In using block
Caught exception
Creating
Caught exception
请注意如何有没有转让对象初始化行。
Note how there's no "Disposing Object initializer" line.