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)

然而,对于上述所有示例,仅执行 true 运算符。那么 C# 中的 false 运算符有什么用呢?

注意:可以在此处此处此处找到更多示例。

4

5 回答 5

65

您可以使用它来覆盖&&and||运算符。

&&and||运算符不能被覆盖,但是如果你覆盖, |,&并且true编译false器将以正确的方式调用|&当你编写||and时&&

例如,查看这段代码(来自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;
}

这显然是一个副作用,而不是它的预期使用方式,但它很有用。

于 2008-08-28T21:02:48.333 回答
26

Shog9 和 Nir:谢谢你的回答。这些答案将我指向Steve Eichert 的文章,它指向了我msdn

操作 x && y 被评估为 T.false(x) ?x : T.&(x, y),其中 T.false(x) 是对 T 中声明的运算符 false 的调用,而 T.&(x, y) 是对选定运算符 & 的调用。换句话说,首先评估 x 并在结果上调用运算符 false 以确定 x 是否肯定为假。然后,如果 x 肯定为假,则操作的结果是先前为 x 计算的值。否则,对 y 求值,并在先前为 x 计算的值和为 y 计算的值上调用选定的运算符 & 以产生操作结果。

于 2008-08-28T21:23:27.397 回答
14

您链接到 http://msdn.microsoft.com/en-us/library/6x6y6z4d.aspx的页面说明了它们的用途,这是在引入可空值类型之前处理可空布尔值的一种方式。

我猜现在它们对与 ArrayList 相同的东西有好处 - 即绝对没有。

于 2008-08-28T20:28:54.640 回答
7

AFAIK,它将用于测试错误,例如当&&操作员发挥作用时。请记住,&& 短路,所以在表达式中

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

mFalse.false()被调用,并且在返回true时表达式被简化为对 'mFalse.true()' 的调用(然后应该返回false,否则事情会变得很奇怪)。

请注意,您必须实现该&运算符才能编译该表达式,因为它在 ifmFalse.false()返回时使用false

于 2008-08-28T20:36:16.620 回答
3

从您链接到的 MSDN 文章中可以看出,在将 Nullable(即 int?、bool? 等)类型引入 C#2 语言之前,提供了可空的布尔类型。因此,您将存储一个内部值,指示该值是 true 还是 false 或 null,即在您的示例中,>0 表示 true,<0 表示 false,==0 表示 null,然后您将获得 SQL 样式的 null 语义。您还必须实现 .IsNull 方法或属性,以便可以显式检查无效性。

与 SQL 相比,想象一个表 Table,其中 3 行的值 Foo 设置为 true,3 行的值 Foo 设置为 false,3 行的值 Foo 设置为 null。

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 个值等于 true,3 个值等于 false,3 个值等于 null。在这种情况下,totalCount 将评估为 6。但是,如果我们将代码重写为:-

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

然后 totalCount 将评估为 9。

链接的 MSDN 文章中关于 false 运算符的 DBNull 示例演示了 BCL 中具有这种确切行为的类。

实际上,结论是你不应该使用它,除非你完全确定你想要这种类型的行为,最好只使用更简单的可空语法!

更新:我刚刚注意到您需要手动覆盖逻辑运算符!,|| 和 && 使其正常工作。我相信错误运算符会输入这些逻辑运算符,即表示真、假或“否则”。如另一条评论中所述!x 不会立即起作用;你必须超载!奇怪!

于 2008-08-28T20:36:10.893 回答