Для чого корисний хибний оператор у C #?


107

У C # є два дивні оператори:

Якщо я розумію це право, ці оператори можуть використовуватися у типах, які я хочу використовувати замість булевого виразу та де я не хочу надавати неявну конверсію bool.

Скажімо, у мене такий клас:

    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;
        }

    }

Тож я можу написати наступний код:

    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)

Однак для всіх наведених вище прикладів виконується лише справжній оператор. То для чого корисний хибний оператор в C #?

Примітка. Більше прикладів можна знайти тут , тут і тут .


Сучасні документи можна знайти на docs.microsoft.com/en-us/dotnet/csharp/language-reference/… . Документи припускають, що немає жодних причин визначати цього оператора, оскільки C # 2.0 додав нульові типи.
Марк Амері

Відповіді:


65

Ви можете використовувати його для зміни &&та ||операторів.

В &&і ||оператори не можуть бути перевизначені, але якщо ви перевизначити |, &, trueі falseточно правильний шлях компілятор буде дзвонити |і &коли ви пишете ||і &&.

Наприклад, подивіться на цей код (з http://ayende.com/blog/1574/nhibernate-criteria-api-operator-overloading - де я дізнався про цей трюк; заархівована версія @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;
}

Це, очевидно, побічний ефект, а не спосіб його використання, але він корисний.


ваше посилання - 404. Не впевнений, як ви хочете відредагувати це, тому я залишив це.
користувач7116

Я оновив URL-адресу заархівованою копією, щоб її можна було прочитати.
IAmTimCorey

25

Shog9 та Nir: дякую за відповіді. Ці відповіді вказували мені на статтю Стіва Ейхерта, і це вказувало на msdn :

Операція x&& оцінюється як T.false (x)? x: T. & (x, y), де T.false (x) - викликання помилки оператора, оголошеного в T, а T. & (x, y) - викликом вибраного оператора &. Іншими словами, x спочатку оцінюється, а оператор помилково викликає результат, щоб визначити, чи x напевно невірно. Тоді, якщо x напевно помилковий, результатом операції є значення, яке раніше було обчислено для x. В іншому випадку оцінюється y, а вибраний оператор & викликається значення, обчислене раніше для x, і значення, обчислене для y, для отримання результату операції.


Цікаво, чому вони не обрали (!T.true(x)) ? x : T.&(x, y)натомість логіку.
Des Nerger

14

На сторінці, на яку ви посилаєтесь http://msdn.microsoft.com/en-us/library/6x6y6z4d.aspx, йдеться про те, для чого вони були, що було способом обробки нульових болів до введення типів нульового значення.

Я здогадуюсь, що вони сьогодні гарні для тих же матеріалів, що і ArrayList - тобто абсолютно нічого.


7

AFAIK, це буде використано в тесті на помилковість, наприклад, коли &&оператор вступає в гру. Пам'ятайте, && коротке замикання, так у виразі

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

mFalse.false()викликається, а після повернення trueвираз зводиться до виклику 'mFalse.true ()' (який повинен повернутися false, інакше речі стануть дивними).

Зауважте, що ви повинні реалізувати &оператор, щоб цей вираз зібрався, оскільки він використовується, якщо mFalse.false()повертається false.


3

Це випливає з статті MSDN, яку ви пов’язали з нею, було надано для дозволу змінних булевих типів до введення типу Nullable (тобто int?, Bool? Тощо) на мові в C # 2. Таким чином, ви зберігаєте внутрішнє значення, яке вказує, чи є значення істинним, або хибним, або нульовим, тобто у вашому прикладі> 0 для істинного, <0 для помилкового і == 0 для нульового, і тоді ви отримаєте нульову семантику в стилі SQL. Також вам доведеться реалізувати метод або властивість .IsNull для того, щоб нікчемність могла бути чітко перевірена.

Порівнюючи SQL, уявіть таблицю Таблиця з 3 рядками зі значенням Foo, встановленою на істинне, 3 рядки зі значенням Foo, встановленою на false, і 3 рядки зі значенням Foo, встановленим на нуль.

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

Для підрахунку всіх рядків вам слід зробити наступне:

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

Цей синтаксис "IS NULL" мав би еквівалентний код у вашому класі як .IsNull ().

LINQ робить порівняння з C # ще зрозумілішим: -

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

Уявляючи, що MyTypeEnumberable має абсолютно однаковий вміст бази даних, тобто 3 значення, що дорівнюють істинному, 3 значення рівні хибні та 3 значення, що дорівнюють нулю. У цьому випадку totalCount оцінить до 6 у цьому випадку. Однак, якщо ми переписали код як: -

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

Тоді TotalCount оцінив би до 9.

Приклад DBNull, наведений у пов'язаній статті MSDN про помилковий оператор, демонструє клас у BCL, який має таку точну поведінку.

Насправді висновок полягає в тому, що ви не повинні використовувати це, якщо ви абсолютно не впевнені, що хочете такого типу поведінки, краще просто використовувати набагато простіший зведений синтаксис !!

Оновлення: я щойно помітив, що вам потрібно вручну переохопити логічні оператори !, || і &&, щоб зробити цю роботу належним чином. Я вважаю, що хибний оператор подає в ці логічні оператори, тобто вказує на правду, хибність чи "інше". Як зазначається в іншому коментарі! X не вийде з місця; вам доведеться перевантажувати !. Дивацтво!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.