これらの2つの線の間に違いはありますか?
MyName = (s.MyName == null) ? string.Empty : s.MyName
または
MyName = s.MyName ?? string.Empty
これらの2つの線の間に違いはありますか?
MyName = (s.MyName == null) ? string.Empty : s.MyName
または
MyName = s.MyName ?? string.Empty
s.MyName1回評価するか2回評価するかです。
diffこと
回答:
更新:私はこのトピックをより深く議論するブログ投稿を書きました。 http://www.codeducky.org/properties-fields-and-methods-oh-my/
通常、同じ結果が返されます。ただし、最初の例ではゲッターが2回実行され、2番目の例では1回しか実行されないMyNameため、プロパティの場合に顕著な違いが発生する場合がいくつかありますMyName。
たとえば、MyName2回実行するとパフォーマンスが異なる場合があります。
string MyName
{
get
{
Thread.Sleep(10000);
return "HELLO";
}
}
または、ステートフルのMyName場合、2回実行すると異なる結果が得られる可能性がありますMyName。
private bool _MyNameHasBeenRead = false;
string MyName
{
get
{
if(_MyNameHasBeenRead)
throw new Exception("Can't read MyName twice");
_MyNameHasBeenRead = true;
Thread.Sleep(10000);
return "HELLO";
}
}
または、別のスレッドで変更できるMyName場合MyNameは、2回実行すると異なる結果が得られる可能性があります。
void ChangeMyNameAsync()
{
//MyName set to null in another thread which makes it
//possible for the first example to return null
Task.Run(() => this.MyName = null);
}
string MyName { get; set; }
実際のコードのコンパイル方法は次のとおりです。最初に三元式の作品:
IL_0007: ldloc.0 // s
IL_0008: callvirt s.get_MyName <-- first call
IL_000D: brfalse.s IL_0017
IL_000F: ldloc.0 // s
IL_0010: callvirt s.get_MyName <-- second call
IL_0015: br.s IL_001C
IL_0017: ldsfld System.String.Empty
IL_001C: call set_MyName
これがnull合体演算子を使用した部分です。
IL_0007: ldloc.0 // s
IL_0008: callvirt s.get_MyName <-- only call
IL_000D: dup
IL_000E: brtrue.s IL_0016
IL_0010: pop
IL_0011: ldsfld System.String.Empty
IL_0016: call s.set_MyName
ご覧のとおり、三項演算子のコンパイル済みコードは、プロパティ値を取得するために2回の呼び出しを行いますが、null合体演算子は1回しか実行しません。
MyName = s.MyName ?? string.EmptyがMyNameプロパティの場合、ゲッターを2回実行しません。したがって、ゲッターを2回実行したくない場合は、2行目を使用する必要があります。
et_MyNameますset_MyName。
?:実際nullには上記の理由で発生する可能性があります。"Value from other thread"上記が実際にnull文字列である場合は、よりわかりやすくなる可能性があります。次に、結果がnullになる可能性があることを示します。オブジェクトがgetアクセサの最初の呼び出しで文字列インスタンスを返し、2番目の呼び出しでのみnullを返すことを決定した場合、ステートフルオブジェクトでも同じことが起こる可能性があります。
プロパティが単純なゲッター以上のものである場合、最初の関数のnull以外の場合に、関数を2回実行している可能性があります。
プロパティがステートフルオブジェクト内にある場合、プロパティへの2回目の呼び出しは異なる結果を返す可能性があります。
class MyClass
{
private IEnumerator<string> _next = Next();
public MyClass()
{
this._next.MoveNext();
}
public string MyName
{
get
{
var n = this._next.Current;
this._next.MoveNext();
return n;
}
}
public static IEnumerator<string> Next()
{
yield return "foo";
yield return "bar";
}
}
また、文字列以外の場合、クラスは==をオーバーロードして、三項演算子とは異なる処理を実行する可能性があります。三項演算子が過負荷になる可能性があるとは思いません。
?:。私はそうする言語を見たことがありません。
はい、どちらも同じで、null合体演算子です。
オペランドがnullでない場合は、左側のオペランドを返します。それ以外の場合は、右側のオペランドを返します。
効率について話すなら、
string MyName = (s.MyName == null) ? string.Empty : s.MyName;
string MyName2 = s.MyName ?? string.Empty;
逆アセンブラーを使用すると、最初のステートメントではコンパイラーが19ステートメントを実行する必要があるのに対し、2番目のステートメントでは12ステートメントしか実行する必要がないことがわかります。
はい、彼らは同じことをします。??nullをチェックするための省略形です。
いいえ。どちらも同じことをしています。2つ目は効率的です。nullでない場合は、実際の値を返します。それ以外の場合は、右側の値が返されます。
これを参照してくださいhttp://msdn.microsoft.com/en-us/library/ms173224.aspx
お役に立てれば。