题
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 运算符有什么用呢?
解决方案
您可以使用它来覆盖 &&
和 ||
运营商。
这 &&
和 ||
运算符不能被覆盖,但如果您覆盖 |
, &
, 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;
}
这显然是一个副作用,而不是它的预期使用方式,但它很有用。
其他提示
您链接到的页面 http://msdn.microsoft.com/en-us/library/6x6y6z4d.aspx 说明了它们的用途,这是在引入可为空值类型之前处理可为空布尔值的一种方法。
我猜现在它们适合与 ArrayList 相同的东西 - 即绝对没有。
AFAIK,它将用于错误测试,例如当 &&
运算符开始发挥作用。请记住,&& 短路,因此在表达式中
if ( mFalse && mTrue)
{
// ... something
}
mFalse.false()
被调用,返回后 true
该表达式被简化为对“mFalse.true()”的调用(然后应该返回 false
, ,否则事情会变得很奇怪)。
请注意,您必须实施 &
运算符以便编译该表达式,因为它使用了 if mFalse.false()
回报 false
.
从您链接到的 MSDN 文章看来,提供它是为了允许在 Nullable 之前使用可空布尔类型(即int?、bool? 等)类型被引入到 C#2 语言中。因此,您将存储一个内部值,指示该值是真、假还是空,即在您的示例中,>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。
有关 false 运算符的链接 MSDN 文章中给出的 DBNull 示例演示了 BCL 中具有这种确切行为的类。
实际上,结论是你不应该使用它,除非你完全确定你想要这种类型的行为,最好只使用更简单的可为空语法!
更新: 我只是注意到您需要手动覆盖逻辑运算符!和&&使这项工作正常。我相信错误运算符会输入到这些逻辑运算符中,即表明真实、虚假或“其他”。正如另一条评论中所述 !x 不会立即起作用;你必须超载!奇怪!