Câu trả lời:
Đó là toán tử điều kiện null . Về cơ bản nó có nghĩa là:
"Đánh giá toán hạng thứ nhất; nếu đó là null, hãy dừng lại, với kết quả là null. Nếu không, hãy đánh giá toán hạng thứ hai (với tư cách là thành viên của toán hạng thứ nhất)."
Trong ví dụ của bạn, vấn đề là nếu a
là null
, sau đó a?.PropertyOfA
sẽ đánh giá để null
thay vì ném một ngoại lệ - sau đó nó sẽ so sánh rằng null
tài liệu tham khảo với foo
(sử dụng chuỗi của ==
quá tải), tìm họ không bình đẳng và thực hiện sẽ đi vào cơ thể của if
tuyên bố .
Nói cách khác, nó như thế này:
string bar = (a == null ? null : a.PropertyOfA);
if (bar != foo)
{
...
}
... ngoại trừ việc đó a
chỉ được đánh giá một lần.
Lưu ý rằng điều này cũng có thể thay đổi loại biểu thức. Ví dụ, xem xét FileInfo.Length
. Đó là một thuộc tính của loại long
, nhưng nếu bạn sử dụng nó với toán tử điều kiện null, thì bạn kết thúc bằng một biểu thức của loại long?
:
FileInfo fi = ...; // fi could be null
long? length = fi?.Length; // If fi is null, length will be null
Nó có thể rất hữu ích khi làm phẳng một đối tượng phân cấp và / hoặc ánh xạ. Thay vì:
if (Model.Model2 == null
|| Model.Model2.Model3 == null
|| Model.Model2.Model3.Model4 == null
|| Model.Model2.Model3.Model4.Name == null)
{
mapped.Name = "N/A"
}
else
{
mapped.Name = Model.Model2.Model3.Model4.Name;
}
Nó có thể được viết như thế (logic tương tự như trên)
mapped.Name = Model.Model2?.Model3?.Model4?.Name ?? "N/A";
Ví dụ làm việc DotNetFiddle.Net .
( toán tử kết hợp ?? hoặc null khác với toán tử có điều kiện? hoặc null ).
Nó cũng có thể được sử dụng ngoài các toán tử gán với Action. Thay vì
Action<TValue> myAction = null;
if (myAction != null)
{
myAction(TValue);
}
Nó có thể được đơn giản hóa để:
myAction?.Invoke(TValue);
sử dụng hệ thống;
public class Program
{
public static void Main()
{
Action<string> consoleWrite = null;
consoleWrite?.Invoke("Test 1");
consoleWrite = (s) => Console.WriteLine(s);
consoleWrite?.Invoke("Test 2");
}
}
Kết quả:
Kiểm tra 2
|| Model.Model2.Model3.Model4.Name == null
để có cùng logic, nếu không, trong trường hợp Model.Model2.Model3.Model4.Name
là null
, mapped.Name
sẽ ở lạinull
Model.Model2.Model3.Model4.Name
có null
.
else
-branch và có mapped.Name = Model.Model2.Model3.Model4.Name -> mapped.Name = null
, trong khi ví dụ thứ hai của bạn sẽ thay thế mapped.Name = "N/A"
. Xem DotNetFiddle đã chỉnh sửa
Điều này tương đối mới đối với C # giúp chúng ta dễ dàng gọi các hàm liên quan đến các giá trị null hoặc không null trong chuỗi phương thức.
cách cũ để đạt được điều tương tự là:
var functionCaller = this.member;
if (functionCaller!= null)
functionCaller.someFunction(var someParam);
và bây giờ nó đã được thực hiện dễ dàng hơn nhiều chỉ với:
member?.someFunction(var someParam);
Tôi thực sự khuyên bạn nên đọc nó ở đây:
https://docs.microsoft.com/en-us/dotnet/csharp/lingu-reference/operators/null-conditable-operators