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更多的例子。
您可以使用它来覆盖&&
和||
运营商。
&&
和||
操作符不能被覆盖,但是如果你重写|
, &
, true
和false
的编译器会以正确的方式调用|
当你写||
和&&
。
例如,看看这个代码(从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计算的值以产生运算的结果。
您链接到http://msdn.microsoft.com/en-us/library/6x6y6z4d.aspx的页面说明了它们的用途,这是在引入可空值types之前处理可空布尔值的一种方法。;
我想现在他们对ArrayList同样的东西是好的 – 也就是说什么都没有。
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不会在蝙蝠身上起作用; 你必须超载! 怪事!