16

Câu hỏi nhanh ở đây về các câu lệnh ngắn mạch trong C#. Với một câu lệnh if như thế này:Đánh giá tuyên bố mạch ngắn - điều này có được đảm bảo không? [C#]

if (MyObject.MyArray.Count == 0 || MyObject.MyArray[0].SomeValue == 0) 
{ 

//.... 
} 

Có đảm bảo đánh giá đó sẽ dừng lại sau khi phần "MyArray.Count", với điều kiện phần là đúng? Nếu không, tôi sẽ nhận được một ngoại lệ null trong phần thứ hai.

+1

Trong trường hợp bạn hỏi câu hỏi này vì bạn * đã nhận được ngoại lệ tham chiếu null từ mã trên, có thể vì 'MyArray' là null hoặc' MyArray [0] 'chứa một giá trị rỗng. Xem câu trả lời của tôi. –

Trả lời

34

Có, điều này được đảm bảo.

C# Language Specification - 7.11 Conditional logical operators:

Các &&|| nhà khai thác này được gọi là các toán tử logic có điều kiện. Chúng cũng được gọi là toán tử logic "ngắn mạch".

Do đó họ sẽ hỗ trợ logic ngắn circuiting theo định nghĩa - bạn có thể dựa vào hành vi này.

Bây giờ điều quan trọng là để thực hiện một sự phân biệt giữa một có điều kiện điều hành và một nhà điều hành logic:

  • Chỉ các nhà khai thác có điều kiện hỗ trợ ngắn mạch, khai thác hợp lý thì không.
  • Các toán tử logic của C# trông giống như các đối tác có điều kiện của chúng, nhưng với một ký tự ít hơn nên OR hợp lý là | và logic AND là &.
  • Các toán tử logic có thể bị quá tải nhưng các toán tử điều kiện không thể (điều này là một chút kỹ thuật khi đánh giá điều kiện có liên quan đến độ phân giải quá tải và độ phân giải quá tải này có thể giải quyết được quá tải tùy chỉnh của toán tử logic của loại. giới hạn ở một mức độ nhất định).
+1

+1 để thực sự trích dẫn CLS. – Polynomial

5

Vâng, nó được đảm bảo, nhưng bạn vẫn có thể có được một ngoại lệ tham chiếu null nếu myArray là null (hoặc MyObject cho rằng vấn đề rõ ràng).

0

Tôi thích sử dụng các nhà điều hành & &, bởi vì bạn sau đó kiểm tra một dương tính (mảng của tôi chứa items), chứ không phải là tiêu cực (lỗi của tôi không chứa items):

if (MyObject.MyArray.Count > 0 && MyObject.MyArray[0].SomeValue == 0) 
{ 

//.... 
} 

này cũng được đảm bảo ngắn mạch.

+0

Kết quả của mã này không giống như của anh ta. Trong của mình, nếu đếm là 0, nó ngắn mạch và đi vào khối. Trong của bạn, nó * chỉ * nhập vào khối trên giá trị của phần tử đầu tiên là 0. –

2

Chỉ cần một quan sát nhỏ.

Bạn nói điều này:

Nếu không tôi sẽ nhận được một rỗng ngoại lệ trong phần thứ hai. (nhấn mạnh mỏ)

Điều này không đúng. Nếu ngắn mạch không được bảo đảm, bạn có thể nhận được một IndexOutOfRangeException trong phần thứ hai.

Đó là vẫn có thể bạn có thể nhận được một NullReferenceException, nếu mục đầu tiên trong đối tượng của bạn thực sự là null (hoặc nếu bất kỳ của các đối tượng khác trong biểu có).

Các chỉ hoàn toàn kiểm tra an toàn sẽ là:

bool conditionHolds = 
    MyObject == null || 
    MyObject.MyArray == null || 
    MyObject.MyArray.Count == 0 || 
    MyObject.MyArray[0] == null || 
    MyObject.MyArray[0].SomeValue == 0; 

if (conditionHolds) 
{ 
    //.... 
} 
+1

Tôi nghĩ bạn quan tâm: nếu (! ConditionHolds) – riffnl

+0

@riffnl: Không, tôi chỉ làm ví dụ của mình phù hợp với mã của OP. (Anh ấy/cô ấy có vẻ muốn mã để làm điều gì đó trong trường hợp tiêu cực.) –

2

Vâng,

Đối VÀ hoạt động nếu một trong các toán hạng được đánh giá là false thì tổng biểu đánh giá là false thì sẽ có không cần đánh giá các biểu thức còn lại, Và trong trường hợp HOẶC hoạt động nếu bất kỳ toán hạng nào được đánh giá là đúng thì đánh giá còn lại có thể bị bỏ qua

Vì vậy, bằng cách sử dụng & & hoặc || toán tử, toàn bộ biểu thức có thể được đánh giá là đúng hoặc sai mà không đánh giá tất cả các biểu thức con.

Nhưng cũng xem xét số side effect của nó. This article có thể hữu ích để hiểu đánh giá ngắn mạch theo chiều sâu với một số ví dụ thực tế.

Các vấn đề liên quan