C#中的错误运算符有什么用?
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运算符。那么Cgood中的错误运算符有什么用呢?
注意:更多示例可以在此处,此处和此处找到。
解决方案
回答
我们链接到http://msdn.microsoft.com/zh-cn/library/6x6y6z4d.aspx的页面上说明了它们的作用,这是在引入可空值类型之前处理可空布尔的一种方法。
我想现在它们对于与ArrayList相同的东西很有用,即绝对没有。
回答
在我们链接到它的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使与Ceven的比较更加清晰:
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不会奏效。你必须超载!怪异的!
回答
AFAIK,它将用于测试是否为假,例如当&&
运算符开始起作用时。请记住,&&短路,所以在表达式中
if ( mFalse && mTrue) { // ... something }
调用了mFalse.false(),并在返回true时将表达式简化为对mFalse.true()的调用(然后应返回false,否则事情会变得很奇怪)。
请注意,我们必须实现&
运算符才能编译该表达式,因为如果mFalse.false()返回false时将使用该运算符。
回答
我们可以使用它来覆盖&&
和||
运算符。
不能覆盖&&
和||
运算符,但是如果以完全正确的方式覆盖|
,&&,
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:
感谢回答。这些答案使我想到了史蒂夫·艾希特(Steve Eichert)的文章,并指出了msdn:
The operation x && y is evaluated as T.false(x) ? x : T.&(x, y), where T.false(x) is an invocation of the operator false declared in T, and T.&(x, y) is an invocation of the selected operator &. In other words, x is first evaluated and operator false is invoked on the result to determine if x is definitely false. Then, if x is definitely false, the result of the operation is the value previously computed for x. Otherwise, y is evaluated, and the selected operator & is invoked on the value previously computed for x and the value computed for y to produce the result of the operation.