在C#中,我可以编写如下内容:
using (new MyDisposableClass().MethodA());
分号会导致显示编译器警告,指出可能出错的空语句。我没有运行上面的代码但是仍然不会调用该方法吗?
这种编码惯例有什么用途?我在这里看到了另一个关于此问题的帖子,但我要求现在存在差异/因此有不同的回复。
由于
答案 0 :(得分:11)
此代码基本上转换为
MyDisposableClass tmp = new MyDisposableClass().MethodA();
try
{
}
finally
{
if( tmp != null )
tmp.Dispose();
}
基本上,您将调用的结果部署到MethodA
,而不是处置可能意图的MyDisposableClass
。
使用声明后的;
是合法的,但警告提示您可能错误地将其添加到那里。例如,以下代码将无法编译:
using( var tmp = new MyDisposableClass() );
{
tmp.MethodA();
}
解析器评估两个完全独立的块,编译器可以看到它就像你输入了这个:
using( var tmp = new MyDispoableClass() )
{
}
{
tmp.MethodA();
}
很容易错过一个悬空;
,所以编译器警告只是暗示你可能想要做其他事情。有时候需要更简洁的陈述,我认为表明它是有目的的最佳方式是使用{}
而不是;
。
using( new MyDisposableClass().MethodA() ){}
请注意,这是调用MethodA的调用结果 - 而不是MyDisposableClass实例。您的代码实际上应该写为
using( var tmp = new MyDisposableClass() ){ tmp.MethodA(); }
答案 1 :(得分:3)
using语句可以用作子句的开头,在最后处理即时对象。换句话说:
using (var foo = new bar())
{
SomeStatments();
}
//foo is disposed
或
using (var foo = new bar())
SomeStatments();
//foo is disposed
您的分号未结束using
语句。它实际上是在using
语句之后结束一个空子句。这通常不是程序员的真实意图。因此,编译器发出“可能错误的空语句”警告。
更新:假设您在问题中列出的代码是实际代码,那么您应该将MethodA
转换为static
方法,因为您显然没有强制执行约束或依赖任何集体成员。
答案 2 :(得分:2)
为什么要设法聪明?
这应该是等价的,未来的开发人员不必谷歌更简洁的语法可能意味着什么。
//By the name of the example, I can assume that MyDisposableClass
//implements IDisposable
using (MyDisposableClass something = new MyDisposableClass())
{
//Assuming the example code compiles, then the return value of MethodA
//implemented IDisposable, too.
using(something.MethodA())
{
};
}
如果你只需要一次电话后就需要处理一些东西,为什么不让MethodA清理那些需要清理的东西呢?
答案 3 :(得分:1)
我认为写这个更清楚:
using (var myDisposable = new MyDisposableClass())
{
myDisposable.MethodA();
}
您拥有它的方式,MethodA
的结果实际上将被视为IDisposable
实施。
答案 4 :(得分:0)
也许有助于此示例:
public static class Helper {
public static void Using<T>( Action<T> action ) where T : IDisposable, new() {
var obj = new T();
action( obj );
}
}
// ...
Helper.Using<MyDisposableClass>( cls => cls.MethodA() );
Helper.Using<OtherClass>( cls => {
for( int i = 0; i < 5; i++ ) { cls.DoRandom(); }
} );
答案 5 :(得分:0)
你可能很想使用这种风格。它确实调用了该方法。但它充其量只是一个成语,并且更有可能在几个月内让包括你在内的下一位读者感到困惑,而不是启发。
即使更换“;”使用空块(消除了编译器警告)可能会在以后读取时导致头部划伤 - 并且记住代码读取比写入更频繁。
保罗亚历山大的回答是正确的,但我没有足够的声誉来评论它。
我曾经在我对这个方法抛出异常的副作用感兴趣的场合使用过它:
try {
using (var _ = File.Open(logPath, FileMode.Open, FileAccess.Read)) { }
} catch (Exception ex) { ... }
File.Open返回一个必须关闭或处理的FileStream。但我真的不喜欢它。我最终命名变量并在块中放置一个显式的Close。我觉得以后会更容易理解。
答案 6 :(得分:-1)
有时会生成编译器警告,然后在您继续键入时不会清除。尝试构建解决方案,看看它是否消失。
另外,我不确定你指的是什么逗号。你的意思是行尾的分号吗?
答案 7 :(得分:-2)
此方法实质上将调用MethodA(),然后永远不会使用它。 '使用'仅在特定的使用块内使用括号中的任何内容。然后它超出了范围。所以:
using (new MyDisposableClass().MethodA())
{
//Code that uses MethodA()
}
...不应该提供该错误,但在使用块之外仍然无法访问MethodA()。
澄清:
您仍然可以在程序的其他位置调用new MyDisposableClass().MethodA()
,但代码using (new MyDisposableClass().MethodA())
中的特定调用将超出范围且无法访问。