Почему 1 && 2 в C # ложно? - PullRequest
13 голосов
/ 05 марта 2011

Я разочаровался в своем другом вопросе . Итак, я написал этот пример.

В C ниже верно. Посмотреть демо

int main()
{
printf("%d", 1 && 2);
return 0;
}

Выход:

1

В C #. Это ЛОЖЬ. ПОЧЕМУ это ложно? Также я не понимаю, почему мне нужно было создать оператор bool в этом примере, но не тот, что в моем другом вопросе, но неважно. Почему ниже ложный? это не имеет смысла для меня.

Кстати, логика, делающая следующее ложное, описана здесь

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            MyInt a=1, b=2;
            bool res=a && b;
            Console.WriteLine("result is {0}", res);
        }

        class MyInt
        {
            public int val;
            public static bool operator true(MyInt t) { return t.val != 0; }
            public static bool operator false(MyInt t) { return t.val == 0; }
            public static MyInt operator &(MyInt l, MyInt r) { return l.val & r.val; }
            public static MyInt operator |(MyInt l, MyInt r) { return l.val | r.val; }
            public static implicit operator MyInt(int v) { return new MyInt() { val = v }; }
            public static implicit operator bool(MyInt t) { return t.val != 0; }
        }
    }
}

Ответы [ 4 ]

22 голосов
/ 05 марта 2011

В C нет bool. Соглашение состоит в том, что 0 является false и != 0 является true. if оператор обрабатывает результат условного выражения именно таким образом.

В C++ bool был введен. Но это было совместимо со старыми правилами, 0 обрабатывалось как false и false как 0, и было неявное преобразование между int и bool.

В C # это не так: есть bool и int, и они не конвертируемы друг в друга. Это то, что говорит C # Standard. Период.

Поэтому, когда вы пытались переопределить совместимость bool и int, вы допустили ошибку. Вы используете &&, который является логическим оператором, но в C # вы не можете переопределить его и только &, который реализован как побитовый. 1 & 2 == 0 == false! вот оно!

Вы даже не должны перегружать битовые единицы, чтобы поддерживать совместимость, вам просто нужно оставить operator true и false.

Этот код работает так, как вы ожидаете:

class Programx
{
    static void Main(string[] args)
    {
        MyInt a = 1, b = 2;
        bool res = a && b;
        Console.WriteLine("result is {0}", res);
    }

    class MyInt
    {
        public int val;
        public static bool operator true(MyInt t)
        {
            return t.val != 0;
        }
        public static bool operator false(MyInt t)
        {
            return t.val == 0;
        }
        public static implicit operator MyInt(int v)
        {
            return new MyInt() { val = v };
        }
        public static implicit operator bool(MyInt t)
        {
            return t.val != 0;
        }
    }
}

результат равен True

9 голосов
/ 05 марта 2011

Ваши реализации оператора & и оператора |не правы.Эти двоичные операторы имеют побитовые значения при применении к целочисленным типам, и применительно к булевым типам или классам, которые имеют свои собственные & и |операторы, они имеют логическую семантику «И» и «ИЛИ» (являясь кузенами без короткого замыкания && и ||).Правильные реализации будут выглядеть следующим образом:

operator &(MyInt l, MyInt r) {return l.val != 0 && r.val != 0);}
operator |(MyInt l, MyInt r) {return l.val != 0 || r.val != 0);}
2 голосов
/ 05 марта 2011

Я постараюсь сделать это проще, поскольку я думаю, что люди слишком усложняют это.

var x = 1 & 2;
// behind the scenes: 0001 AND 0010 = 0000
Console.Write(x); // 0, as shown above

Целые числа НЕ могут использоваться как булевы в C #. Результат:

if (1 && 2) // compile error
var x = 1 && 2; // compile error

Нет смысла спрашивать, почему Integer нельзя использовать в качестве логического значения в C #, просто нельзя. Система типов не позволяет этого. Если бы кто-то реализовал свой собственный класс Integer, он мог бы предоставить неявные преобразования из своего типа в bool, но int делает , а не . Вы также должны сделать выбор при перегрузке; Вы хотите побитовое поведение или логическое поведение. Вы не можете иметь оба.

Некоторые языки допускают значения 0, "", [] в качестве значений 'falsey'. C # нет. Преодолей это и используй bool, если ты делаешь логическую логику. Если все остальное терпит неудачу, Convert.ToBoolean в int вернет true для всех ненулевых значений.

1 голос
/ 05 марта 2011
public static MyInt operator &(MyInt l, MyInt r) { return l.val & r.val; }

Если я правильно прочитал связанную статью, res = a && b будет "расширен" до:

MyInt.false(a) ? a : MyInt.&(a, b)

MyInt.false (a) имеет значение false, поэтому оценивается как:

MyInt.&(a, b)

который "расширяется" до:

a.val & b.val

, который (1 & 2) == 0, и, таким образом, false.

...