Почему 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
.