Toán tử false trong C # có tác dụng gì?


107

Có hai toán tử kỳ lạ trong C #:

Nếu tôi hiểu đúng điều này, các toán tử này có thể được sử dụng trong các kiểu mà tôi muốn sử dụng thay vì biểu thức boolean và nơi tôi không muốn cung cấp một chuyển đổi ngầm định thành bool.

Giả sử tôi có một lớp học sau:

    public class MyType
    {
        public readonly int Value;

        public MyType(int value)
        {
            Value = value;
        }

        public static bool operator true (MyType mt)
        {
            return  mt.Value > 0;
        }

        public static bool operator false (MyType mt)
        {
            return  mt.Value < 0;
        }

    }

Vì vậy, tôi có thể viết mã sau:

    MyType mTrue = new MyType(100);
    MyType mFalse = new MyType(-100);
    MyType mDontKnow = new MyType(0);

    if (mTrue)
    {
         // Do something.
    }

    while (mFalse)
    {
        // Do something else.
    }

    do
    {
        // Another code comes here.
    } while (mDontKnow)

Tuy nhiên, đối với tất cả các ví dụ trên chỉ có toán tử true được thực thi. Vậy toán tử false trong C # có tác dụng gì?

Lưu ý: Có thể tìm thấy nhiều ví dụ hơn ở đây , ở đâyở đây .


Tài liệu hiện đại có thể được tìm thấy tại docs.microsoft.com/en-us/dotnet/csharp/language-reference/… . Các tài liệu gợi ý rằng không có lý do gì để xác định toán tử này nữa vì C # 2.0 đã thêm các kiểu nullable.
Mark Amery

Câu trả lời:


65

Bạn có thể sử dụng nó để ghi đè các toán tử &&||.

Các &&||các nhà khai thác không thể ghi đè, nhưng nếu bạn ghi đè |, &, truefalsetrong cách chính xác đúng trình biên dịch sẽ gọi |&khi bạn viết ||&&.

Ví dụ: hãy xem mã này (từ http://ayende.com/blog/1574/nhibernate-criteria-api-operator-overloading - nơi tôi phát hiện ra thủ thuật này; phiên bản được lưu trữ bởi @BiggsTRC):

public static AbstractCriterion operator &(AbstractCriterion lhs, AbstractCriterion rhs)
{
       return new AndExpression(lhs, rhs);
}

public static AbstractCriterion operator |(AbstractCriterion lhs, AbstractCriterion rhs)
{
       return new OrExpression(lhs, rhs);
}

public static bool operator false(AbstractCriterion criteria)
{
       return false;
}
public static bool operator true(AbstractCriterion criteria)
{
       return false;
}

Đây rõ ràng là một tác dụng phụ và không phải là cách nó dự định được sử dụng, nhưng nó hữu ích.


liên kết của bạn là 404. Không chắc bạn muốn chỉnh sửa nó như thế nào, vì vậy tôi đã để nguyên.
user7116

Tôi đã cập nhật URL bằng một bản sao được lưu trữ để vẫn có thể đọc được.
IAmTimCorey

25

Shog9 và Nir: cảm ơn vì câu trả lời của bạn. Những câu trả lời đó đã chỉ tôi đến bài báo của Steve Eichert và nó chỉ tôi đến msdn :

Phép toán x && y được đánh giá là T.false (x)? x: T. & (x, y), trong đó T.false (x) là lệnh gọi của toán tử được khai báo sai trong T và T. & (x, y) là lệnh gọi của toán tử đã chọn &. Nói cách khác, x được đánh giá đầu tiên và toán tử false được gọi trên kết quả để xác định xem x có chắc chắn là sai hay không. Sau đó, nếu x chắc chắn là sai, kết quả của phép toán là giá trị đã được tính trước đó cho x. Nếu không, y được đánh giá và toán tử đã chọn & được gọi trên giá trị được tính trước đó cho x và giá trị được tính cho y để tạo ra kết quả của phép toán.


Tôi tự hỏi tại sao họ không chọn sử dụng (!T.true(x)) ? x : T.&(x, y)logic thay thế.
Des Nerger

14

Trang mà bạn liên kết tới http://msdn.microsoft.com/en-us/library/6x6y6z4d.aspx cho biết chúng dùng để làm gì, đó là một cách xử lý các bools nullable trước khi các kiểu giá trị nullable được giới thiệu.

Tôi đoán ngày nay chúng tốt cho những thứ tương tự như ArrayList - tức là hoàn toàn không có gì.


7

AFAIK, nó sẽ được sử dụng trong một bài kiểm tra về sai, chẳng hạn như khi &&nhà điều hành hoạt động. Hãy nhớ && đoản mạch, vì vậy trong biểu thức

if ( mFalse && mTrue) 
{
   // ... something
}

mFalse.false()được gọi, và khi trả về true, biểu thức được rút gọn thành lời gọi 'mFalse.true ()' (sau đó sẽ trả về false, nếu không mọi thứ sẽ trở nên kỳ lạ).

Lưu ý rằng bạn phải triển &khai toán tử để biểu thức đó biên dịch, vì nó được sử dụng nếu mFalse.false()trả về false.


3

Nó xuất hiện từ bài báo MSDN mà bạn đã liên kết với nó được cung cấp để cho phép các kiểu boolean nullable trước kiểu Nullable (tức là int ?, bool?, V.v.) được giới thiệu sang ngôn ngữ trong C # 2. Vì vậy, bạn sẽ lưu trữ một giá trị nội bộ cho biết giá trị đó là true hay false hoặc null, tức là trong ví dụ của bạn> 0 cho true, <0 cho false và == 0 cho null, và sau đó bạn sẽ nhận được ngữ nghĩa null kiểu SQL. Bạn cũng sẽ phải triển khai một phương thức hoặc thuộc tính .IsNull để có thể kiểm tra tính rỗng một cách rõ ràng.

So sánh với SQL, hãy tưởng tượng một bảng Table có 3 hàng với giá trị Foo được đặt thành true, 3 hàng có giá trị Foo được đặt thành false và 3 hàng với giá trị Foo được đặt thành null.

SELECT COUNT(*) FROM Table WHERE Foo = TRUE OR Foo = FALSE
6

Để đếm tất cả các hàng, bạn phải làm như sau: -

SELECT COUNT(*) FROM Table WHERE Foo = TRUE OR Foo = FALSE OR Foo IS NULL
9

Cú pháp 'IS NULL' này sẽ có mã tương đương trong lớp của bạn là .IsNull ().

LINQ làm cho sự so sánh với C # rõ ràng hơn: -

int totalCount = (from s in MyTypeEnumerable
                 where s || !s
                 select s).Count();

Tưởng tượng rằng MyTypeEnumberable có chính xác nội dung của cơ sở dữ liệu, tức là 3 giá trị bằng true, 3 giá trị bằng false và 3 giá trị bằng null. Trong trường hợp này, TotalCount sẽ là 6 trong trường hợp này. Tuy nhiên, nếu chúng tôi viết lại mã là: -

int totalCount = (from s in MyTypeEnumerable
                 where s || !s || s.IsNull()
                 select s).Count();

Sau đó, tổng số tiền sẽ đánh giá là 9.

Ví dụ DBNull được đưa ra trong bài viết MSDN được liên kết về toán tử sai chứng minh một lớp trong BCL có hành vi chính xác này.

Thực tế, kết luận là bạn không nên sử dụng điều này trừ khi bạn hoàn toàn chắc chắn rằng bạn muốn loại hành vi này, tốt hơn là chỉ nên sử dụng cú pháp nullable đơn giản hơn nhiều !!

Cập nhật: Tôi vừa nhận thấy bạn cần ghi đè thủ công các toán tử logic !, || và && để làm cho điều này hoạt động bình thường. Tôi tin rằng toán tử sai đưa vào các toán tử logic này, nghĩa là chỉ ra sự thật, giả mạo hoặc 'khác'. Như đã lưu ý trong một bình luận khác! X sẽ không hoạt động hiệu quả; bạn phải quá tải !. Sự kì lạ!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.