C#可能错误的空语句

时间:2010-05-19 22:11:32

标签: c#

在C#中,我可以编写如下内容:

using (new MyDisposableClass().MethodA());

分号会导致显示编译器警告,指出可能出错的空语句。我没有运行上面的代码但是仍然不会调用该方法吗?

这种编码惯例有什么用途?我在这里看到了另一个关于此问题的帖子,但我要求现在存在差异/因此有不同的回复。

由于

8 个答案:

答案 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())中的特定调用将超出范围且无法访问。