14

我对我的另一个问题感到沮丧。所以我写了这个例子。

在 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

4 回答 4

22

C里面bool没有。约定即0false!= 0trueif语句完全以这种方式处理条件表达式结果。

C++ bool介绍。但它与旧规则兼容,0被视为falseand falseas ,并且and0之间存在隐式转换。intbool

在 C# 中,情况不一样:有bool并且int它们不能相互转换。这就是 C# 标准所说的。时期。

因此,当您尝试重新实现boolint兼容时,您犯了一个错误。您使用 && 这是逻辑运算符,但在 C# 中您不能覆盖它,只能使用 &,它是按位实现的。1 & 2 == 0 == false!这里是!

你甚至不应该重载按位,为了保持兼容性,你只需要离开operator truefalse.

此代码按您的预期工作:

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

结果为真

于 2011-03-05T12:24:06.400 回答
9

您对 operator& 和 operator| 的实现 错了。这些二元运算符在应用于整数类型时具有按位含义,当应用于布尔类型或具有自己的 & 和 | 的类时 运算符,它们具有逻辑 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);}
于 2011-03-05T12:26:51.280 回答
2

我会尽量让这个简单,因为我认为人们过于复杂了。

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# 没有。克服它,如果您正在执行布尔逻辑,请使用布尔值。如果一切都失败Convert.ToBoolean了,一个 int 将返回true所有非零值。

于 2011-03-05T12:55:07.277 回答
1
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) 为假,因此计算结果为:

MyInt.&(a, b)

其中“扩展”为:

a.val & b.val

即 (1 & 2) == 0,因此false.

于 2011-03-05T12:32:14.043 回答