web-dev-qa-db-ja.com

「条件付き三項式を簡略化する」

_var foo = context.FOOTABLE.FirstOrDefault(); 
var bar = foo != null ? foo.SomeBool : false;
_

Resharperは私に_Simplify conditional ternary expression_と言っています。しかし、FirstOrDefault()はnullを返す可能性があるため、ここではnullチェックが必要だと思います。

それで、私とResharperのどちらが間違っているのですか?

21
Johan

まず、完全な例:

class Foo
{
    public bool SomeBool { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var foo = MaybeFoo();

        var bar = foo != null && foo.SomeBool;

    }

    static Foo MaybeFoo()
    {
        return new Random().Next() < 10 ? null : new Foo();
    }
}

ここで、MaybeFooは、nullを返すこともあれば、Fooを返すこともあるメソッドです。 Randomを使用したので、R#は、常にnullまたはnot-nullであると自動的に判断されません。

さて、あなたがこの行で言うように:

        var bar = foo != null ? foo.SomeBool : false;

R#は検査を提供します条件演算子を単純化します。これはどういう意味ですか?まあ、いつものように、私たちはできます Alt+Enter 提案を受け入れて、それを何に置き換えたいかを確認します。この場合は次のとおりです。

        var bar = foo != null && foo.SomeBool;

さて、あなたの懸念について:

しかし、FirstOrDefault()はnullを返す可能性があるため、ここではnullチェックが必要だと思います。

それで、私とResharperのどちらが間違っているのですか?

まあ、簡単に言えば、あなたはそうです。ここではまだnullチェックが行われています。&&演算子が短絡していますなので、第2オペランド(foo.SomeBool最初のものがtrueの場合にのみ評価されます。したがって、NullReferenceExceptionfooの場合、nullは存在しません。最初のチェックは失敗し、barにはfalseが割り当てられます。

だから2行

        var bar = foo != null ? foo.SomeBool : false;

そして

        var bar = foo != null && foo.SomeBool;

意味的に同等であり、R#は通常、より簡潔なバージョンを優先します(特に、条件文の明示的なtruesとfalsesは冗長コードのマークであることがよくあります)。そうしない場合は、この検査をオフにすることができます。

36
AakashM

ReSharperは、コードを次のように変更することを提案しています。

var bar = foo != null && foo.SomeBool;

これは三項演算とまったく同じですが、見た目は良くなります。コードのロジックは変更されません。

9