2009-12-11 15 views
6

次の2つのコードスニペットは同じことを達成していますか?これら2つのステートメントは同じですか?

私の元のコード:私は上記のコードは、それを変更する任意の説得力のある理由読みする方がはるかに簡単だと思う

this.SafeFileNames = safeFileNames != null && 
        Convert.ToBoolean(safeFileNames.Value); 

if (safeFileNames != null) 
{ 
    this.SafeFileNames = Convert.ToBoolean(safeFileNames.Value); 
} 
else 
{ 
    this.SafeFileNames = false; 
} 

は良いアイデアは何ReSharperの考えでしたか?
これは速く実行されますか、そして最も重要なのは、コードはまったく同じことでしょうか?

また、:Convert.ToBoolean(safeFileNames.Value);セクションを見ると、確かにnull参照例外が発生する可能性がありますか?

this.SafeFileNames = bool 

ローカルsafeFileNamesは、ここでは、強く型付けされたカスタムオブジェクトであるクラスです:

public class Configuration 
    { 
     public string Name 
     { 
      get; 
      set; 
     } 
     public string Value 
     { 
      get; 
      set; 
     } 
    } 
+3

あなたは最初の部分以来 'NullReferenceExcepton'を取得することはありませんステートメント 'safeFileNames!= null'は短絡してしまい、' Convert.ToBoolean(safeFileNames.Value) 'を打つことはありません - thats the wa y &&は動作します。 – Nate

+2

C#の遅延評価のために、null参照例外が発生しませんでした。 &&ステートメントは常に左側と右側が評価されます。しかし、左側が偽であれば、論理的な結果が既に決定されているので、右側を評価することはありません。したがって、safeFileNamesがnullの場合、Convert.ToBoolean呼び出しは行われません。 このようなことは、コードではよくあることです。 –

+1

したがって&&を理解していれば、左の部分がfalseの場合はfalseを返します。そうでない場合は、右の部分を評価し、正しい部分の結果を返します。 –

答えて

24

あなたが質問したという事実は、前者が優先されることを私に示唆しています。つまり、あなたの質問は、最初のコードが理解しやすいと考えていることを意味し、2番目のコードが同等かどうかはわかりません。ソフトウェア設計の第一の目標は、複雑さを管理することです。それがあなたに今混乱している場合は、後であなたにやって来るかもしれません。

+4

これはすばらしい答えです。 – jason

+0

+1キス[15] –

+0

それを見て非常に良い方法。 –

5

両方の文がまったく同じことを行います。どちらを使うのが好みの問題ですが、私はResharperのバージョンを好む。より簡潔で動きの少ない部品。コードの意図を見やすくする。

+0

this.SafeFileNamesがnullの場合はどうなりますか?確かにConvert.ToBooleanをnullにしようとすると、null参照例外が発生するでしょうか? –

+0

@JL:SafeFileNamesがnullの場合、第2節は実行されません – Randolpho

+0

勝利のために短絡しています。 –

1

これらは同じです。 & &は短絡演算子であるため、safeFileNamesがnullの場合、式の後半は評価されません。

1

これらは同じです。 1ライナーでは、最初の条件が失敗した場合、2番目の条件は評価されません。だからあなたはヌル参照を取得しません。

どちらの場合もILは同じです。

私は2番目のバージョンが好きです。

2

resharperの提案を使用すると、コードの循環的複雑さが軽減されます。

読みやすいかどうかは個人的な意見ですが、私はresharperがあなたに与えた提案を好む。

それらが同一である、とあなたは可読性をしたい場合、私はまた、次のことを提案することができます:

if (safeFileNames != null) 
    this.SafeFileNames = Convert.ToBoolean(safeFileNames.Value); 
else 
    this.SafeFileNames = false; 

または

this.SafeFileNames = safeFileNames != null ? Convert.ToBoolean(safeFileNames.Value) : false 
+0

注:不必要なときに中かっこを削除することは、コードの見栄えを良くすることになります。 –

+0

@Aequtarium、あなたの答えは間違っていたり非効率的ではありません。他の人たちと同じようにエキサイティングではありません。あなたに投票してください。 –

+0

意見はありますが、StyleCopがこれをエラーとしてフラグを立てることに注意してください。一貫性は1つの要因です。もう1つは、if(elseを除く)に2番目のステートメントを追加して、中括弧も追加するのを忘れたときにエラーが発生します。 IDEは通常それをインデントして通知しますが、ビジュアルメモ帳を使用している場合は.... –

1

うん、両方のこれらのステートメントは、あなたがいない、同じことを行います再福音をゴスペルとして取らなければならない、一人の人間が読めるコードと考えるのは、もう一つの混乱である。

あなたのやりたいことをもっと読みやすくするために、いくつかの方法があります。どのタイプの値がsafeFileNamesですか?それはnull可能なブールかもしれないようですね?もしあなたが単に書くことができれば、

this.SafeFileNames = safeFileNames.GetValueOrDefault(); 
0

論理的には同じです。パフォーマンスの差異は無視できる可能性があります。 2番目の形式は条件付きでなくなるため、2番目の形式は一部のプラットフォームでより効率的なバイナリコードに変換される可能性があります。コンディショナル(間違った投機実行)は、CPUを大量に使用する作業でCPUの命令パイプラインを台無しにする可能性があります。しかし、ILとJITterの両方は、これに大きな差をつけるために適切な品質のコードを発行する必要があります。

私はあなたの読みやすさに同意しますが、誰もがそれを共有しているとは限りません。

5

両方のコードでILがあります。私はあなたのコードを取って、ILを見てコンソールアプリケーションを作成しました。結果のILから見ることができるように、1つのメソッド(method2)は4バイト短くなりますが、両方のために実行されるILはほぼ同じであるため、パフォーマンスが上がるまでは...心配する必要はありません。どちらも同じパフォーマンスを持ちます。どちらが読みやすく、あなたの意図をよりよく示すかに焦点を当てます。

マイコード:

class Program 
{ 
    static void Main(string[] args) 
    { 


    } 
    public void method1() 
    { 
     bool? safeFileNames = null; 

     if (safeFileNames != null) 
     { 
      SafeFileNames = Convert.ToBoolean(safeFileNames.Value); 
     } 
     else 
     { 
      SafeFileNames = false; 
     } 
    } 
    public void method2() 
    { 
     bool? safeFileNames = null; 
     SafeFileNames = safeFileNames != null && Convert.ToBoolean(safeFileNames.Value); 
    } 
    public static bool SafeFileNames { get; set; } 
} 

IL方法1:

.method public hidebysig instance void method1() cil managed 
{ 
    // Code size  42 (0x2a) 
    .maxstack 1 
    .locals init ([0] valuetype [mscorlib]System.Nullable`1<bool> safeFileNames) 
    IL_0000: ldloca.s safeFileNames 
    IL_0002: initobj valuetype [mscorlib]System.Nullable`1<bool> 
    IL_0008: ldloca.s safeFileNames 
    IL_000a: call  instance bool valuetype [mscorlib]System.Nullable`1<bool>::get_HasValue() 
    IL_000f: brfalse.s IL_0023 
    IL_0011: ldloca.s safeFileNames 
    IL_0013: call  instance !0 valuetype [mscorlib]System.Nullable`1<bool>::get_Value() 
    IL_0018: call  bool [mscorlib]System.Convert::ToBoolean(bool) 
    IL_001d: call  void ConsoleApplication5.Program::set_SafeFileNames(bool) 
    IL_0022: ret 
    IL_0023: ldc.i4.0 
    IL_0024: call  void ConsoleApplication5.Program::set_SafeFileNames(bool) 
    IL_0029: ret 
} // end of method Program::method1 

IL方法2について:

.method public hidebysig instance void method2() cil managed 
{ 
    // Code size  38 (0x26) 
    .maxstack 1 
    .locals init ([0] valuetype [mscorlib]System.Nullable`1<bool> safeFileNames) 
    IL_0000: ldloca.s safeFileNames 
    IL_0002: initobj valuetype [mscorlib]System.Nullable`1<bool> 
    IL_0008: ldloca.s safeFileNames 
    IL_000a: call  instance bool valuetype [mscorlib]System.Nullable`1<bool>::get_HasValue() 
    IL_000f: brfalse.s IL_001f 
    IL_0011: ldloca.s safeFileNames 
    IL_0013: call  instance !0 valuetype [mscorlib]System.Nullable`1<bool>::get_Value() 
    IL_0018: call  bool [mscorlib]System.Convert::ToBoolean(bool) 
    IL_001d: br.s  IL_0020 
    IL_001f: ldc.i4.0 
    IL_0020: call  void ConsoleApplication5.Program::set_SafeFileNames(bool) 
    IL_0025: ret 
} // end of method Program::method2 
+1

私はこれを1点以上与えることができますが、実際の違いを判断するためにILをチェックすると大変です。 –

+0

+1、極端な努力のために、そして多くのありがとう! –

+0

ildasmをほぐしてしばらく遊んでいるような良い言い訳のようです:-) – jvilalta

関連する問題