什么是C#中的错误操作符?

时间:2008-08-28 20:06:02

标签: c# .net syntax

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运算符有什么用呢?

注意:可以找到更多示例hereherehere

5 个答案:

答案 0 :(得分:65)

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

&&||运算符无法覆盖,但如果您覆盖|&truefalse,编写|&时,编译器将以正确的方式调用||&&

例如,请查看此代码(来自http://ayende.com/blog/1574/nhibernate-criteria-api-operator-overloading - 我发现了这个技巧; archived version来自@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;
}

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

答案 1 :(得分:25)

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

  

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

答案 2 :(得分:14)

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

我猜现在他们对ArrayList这样的东西很有用 - 也就是说什么都没有。

答案 3 :(得分:7)

AFAIK,它会在测试中用于假,例如当&&运算符发挥作用时。请记住,&amp;&amp;短路,所以在表达式中

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

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

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

答案 4 :(得分:3)

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

与SQL相比,假设一个表具有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。

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

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

更新:我刚注意到你需要手动覆盖逻辑运算符!,||和&amp;&amp;使这项工作正常。我相信虚假运算符会输入这些逻辑运算符,即表示真,假或“其他”。正如另一条评论所指出的那样!x不会起作用;你必须超载!古怪!