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运算符有什么用呢?
答案 0 :(得分:65)
您可以使用它来覆盖&&
和||
运算符。
&&
和||
运算符无法覆盖,但如果您覆盖|
,&
,true
和false
,编写|
和&
时,编译器将以正确的方式调用||
和&&
。
例如,请查看此代码(来自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)
与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不会起作用;你必须超载!古怪!