Почему 1 && 2 в С# false?

Я был напуган другим вопросом. Поэтому я написал этот пример.

В C ниже указано значение true. См. Демонстрацию

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

Вывод:

1

В С#. Это ЛОЖЬ. ПОЧЕМУ это ложь? Также я не понимаю, почему мне нужно было создать оператор 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; }
        }
    }
}

Ответ 1

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

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

В С# это не то же самое: есть bool и int, и они не конвертируются в eachother. Это то, что говорит С# Standard. Период.

Поэтому, когда вы попытались переопределить совместимость bool и int, вы сделали ошибку. Вы используете && который является логическим оператором, но в С# вы не можете его переопределить и только &, который реализуется как побитовое. 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

Ответ 2

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

operator &(MyInt l, MyInt r) {return l.val != 0 && r.val != 0);}
operator |(MyInt l, MyInt r) {return l.val != 0 || r.val != 0);}

Ответ 3

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

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

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

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

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

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

Ответ 4

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.