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

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

  • 真正的运营商
  • 虚假的运营商

如果我理解这个权利,这些运算符可以在我想要使用的types中使用,而不是布尔expression式,并且我不想向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) 

然而,对于上面的所有例子,只有真正的操作符被执行。 那么C#中的假运算符有什么用处?

注意: 这里和这里可以find更多的例子。

您可以使用它来覆盖&&|| 运营商。

&&|| 操作符不能被覆盖,但是如果你重写|&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; } 

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

Shog9和Nir:谢谢你的回答。 这些答案指向我史蒂夫Eichert文章 ,并指出我的MSDN :

操作x && y被评估为T.false(x)? x:T。&(x,y),其中T.false(x)是在T中声明的运算符false的调用,T。&(x,y)是所选运算符&的调用。 换句话说,首先计算x,并在结果上调用operator false来确定x是否肯定是false。 那么,如果x肯定是错误的,那么操作的结果就是之前为x计算的值。 否则,y被评估,并且select的运算符&被调用先前为x计算的值和为y计算的值以产生运算的结果。

AFAIK,它将被用于虚假的testing,例如当&&操作符进入时。 请记住,&&短路,所以在expression式中

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

mFalse.false()被调用,当返回true ,expression式被简化为对“mFalse.true()”的调用(然后应该返回false ,否则会变得怪异)。

请注意,必须实现&运算符才能编译该expression式,因为如果mFalse.false()返回false ,则会使用该运算符。

从MSDN文章中可以看出,你提供了允许在Nullable(即int ?, bool?等)types被引入到C#2语言之前的可空布尔types。 因此,你应该存储一个内部值,指示值是true还是false或null,即在你的例子中> 0为true,<0为false,== 0为null,然后你会得到SQL风格的空语义。 您还必须实现.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”语法将在您的类中具有equivilent代码,如.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中的类。

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

更新:我只注意到你需要手动覆盖逻辑运算符!,|| 并&&使其正常工作。 我相信虚假操作符会喂入这些逻辑操作符,即指示真相,虚假或“否则”。 正如另一个评论所指出的那样!x不会在蝙蝠身上起作用; 你必须超载! 怪事!