Có sự khác biệt giữa hai dòng này?
MyName = (s.MyName == null) ? string.Empty : s.MyName
hoặc là
MyName = s.MyName ?? string.Empty
Có sự khác biệt giữa hai dòng này?
MyName = (s.MyName == null) ? string.Empty : s.MyName
hoặc là
MyName = s.MyName ?? string.Empty
s.MyNamemột lần hay hai lần.
diffnó
Câu trả lời:
CẬP NHẬT: Tôi đã viết một bài blog thảo luận sâu hơn về chủ đề này. http://www.codeducky.org/properties-fields-and-methods-oh-my/
Nói chung chúng sẽ trả về cùng một kết quả. Tuy nhiên, có một số trường hợp bạn sẽ gặp phải sự khác biệt đáng chú ý khi MyNamelà một thuộc tính vì MyNamegetter sẽ được thực thi hai lần trong ví dụ đầu tiên và chỉ một lần trong ví dụ thứ hai.
Ví dụ: bạn có thể gặp sự khác biệt về hiệu suất khi thực hiện MyNamehai lần:
string MyName
{
get
{
Thread.Sleep(10000);
return "HELLO";
}
}
Hoặc bạn có thể nhận được các kết quả khác khi thực hiện MyNamehai lần nếu MyNametrạng thái là:
private bool _MyNameHasBeenRead = false;
string MyName
{
get
{
if(_MyNameHasBeenRead)
throw new Exception("Can't read MyName twice");
_MyNameHasBeenRead = true;
Thread.Sleep(10000);
return "HELLO";
}
}
Hoặc bạn có thể nhận được kết quả khác khi thực hiện MyNamehai lần nếu MyNamecó thể được thay đổi trên một chuỗi khác:
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; }
Đây là cách mã thực sự được biên dịch. Đầu tiên là mảnh có biểu thức bậc ba:
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
và đây là phần có toán tử null-kết hợp:
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
Như bạn có thể thấy mã đã biên dịch cho toán tử bậc ba sẽ thực hiện hai lệnh gọi để nhận giá trị thuộc tính, trong khi toán tử liên kết rỗng sẽ chỉ thực hiện 1.
MyName = s.MyName ?? string.Emptysẽ không thực thi getter hai lần nếu MyNamelà một thuộc tính. Vì vậy, nếu bạn không muốn thực thi getter hai lần, thì bạn nên sử dụng dòng thứ hai.
et_MyName, nên được set_MyName.
?:thực sự có thể dẫn đến nullnhững lý do trên. Nó có thể minh họa hơn nếu "Value from other thread"ở trên thực sự là một nullchuỗi. Sau đó, điều đó sẽ cho thấy rằng kết quả có thể là rỗng. Điều tương tự cũng có thể xảy ra với đối tượng trạng thái nếu đối tượng quyết định trả về một cá thể chuỗi trong lần gọi đầu tiên của getaccessoor và trả về null chỉ trên lần gọi thứ hai.
Nếu thuộc tính nhiều hơn một getter đơn giản, bạn có thể đang thực thi một hàm hai lần trong trường hợp khác rỗng cho cái đầu tiên.
Nếu thuộc tính nằm trong một đối tượng trạng thái, thì lệnh gọi thứ hai đến thuộc tính có thể trả về một kết quả khác:
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";
}
}
Ngoài ra, trong trường hợp không phải là chuỗi, lớp có thể quá tải == để thực hiện điều gì đó khác với toán tử bậc ba. Tôi không tin rằng toán tử bậc ba có thể bị quá tải.
?:. Tôi chưa thấy bất kỳ ngôn ngữ nào làm được.
Sự khác biệt duy nhất là bạn đánh giá s.MyNamehai lần hay một lần. Lần đầu tiên sẽ thực hiện hai lần trong trường hợp s.MyNamekhông phải là giá trị rỗng, lần thứ hai sẽ chỉ đánh giá nó một lần.
Trong hầu hết các trường hợp, sự khác biệt này không quan trọng, và tôi sẽ chọn thứ hai vì nó rõ ràng và ngắn gọn hơn.
Đúng, cả hai đều giống nhau và nó là toán tử kết hợp rỗng .
Nó trả về toán hạng bên trái nếu toán hạng không rỗng; nếu không nó trả về toán hạng bên phải.
Nếu chúng ta nói về hiệu quả thì
string MyName = (s.MyName == null) ? string.Empty : s.MyName;
string MyName2 = s.MyName ?? string.Empty;
Nếu tôi sử dụng bộ phổ biến thì tôi có thể thấy rằng câu lệnh đầu tiên cần 19 câu lệnh để được thực thi bởi trình biên dịch trong khi câu lệnh thứ hai chỉ yêu cầu 12 câu lệnh được thực thi.
Vâng, họ cũng làm như vậy. ??là cách viết tắt để kiểm tra null.
Cả hai đều đang làm điều tương tự. Thứ hai là hiệu quả. Giá trị này trả về giá trị thực nếu nó không phải là giá trị rỗng. Nếu không, giá trị bên phải sẽ được trả về.
Tham khảo http://msdn.microsoft.com/en-us/library/ms173224.aspx này
Hi vọng điêu nay co ich.