C#中的错误运算符有什么用?


107

C#中有两个奇怪的运算符:

如果我理解正确的话,这些运算符可以用在我想使用的类型中,而不是布尔表达式中,并且我不想为布尔提供隐式转换。

假设我有以下课程:

    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#中的错误运算符有什么用呢?

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


可以在docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/…中找到现代文档。该文档表明,由于C#2.0添加了可为空的类型,因此不再需要定义此运算符。
Mark Amery

Answers:


65

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

&&||运营商不能被覆盖,但如果重写|&truefalse完全正确的方式编译器会调用|&当你写||&&

例如,看下面的代码(来自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;
}

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


您的链接是404。不确定您要如何编辑它,所以我保留了它。
user7116 2011年

我用存档副本更新了URL,以便仍然可以读取它。
IAmTimCorey 2011年

25

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是否绝对为false。然后,如果x绝对为假,则运算结果为先前为x计算的值。否则,对y求值,并且对先前为x计算的值和为y计算的值调用所选的运算符&,以生成运算结果。


我想知道为什么他们没有选择使用(!T.true(x)) ? x : T.&(x, y)逻辑。
Des Nerger '19


7

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

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

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

请注意,您必须实现&运算符才能编译该表达式,因为如果mFalse.false()return会使用该表达式false


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不会奏效。你必须超载!怪异的!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.