可以显式调用 operator true() 吗?什么时候用来转bool?
Can one call `operator true()` explicitly? When is it used to convert to bool?
出于好奇,我探索了 C# 中的重载运算符。有一个有趣的 post by Eric Lippert 讨论了 C++ 和 C# 中关于 operator&&
的设计决策。在 C# 中,它的重载是通过重载 operator&
加上重载布尔运算符 true
和 false
隐式定义的,这允许语言保留有时必不可少的短路语义。
玩着有点奇葩的operator true()
和false()
发现不能直接调用。相反,它们在某些需要布尔值的地方被隐式调用。据我所知,这些是直接需要 bool 的语言结构,即三元条件运算符和 if 子句,以及对 operator&&
的调用。 ||
当参数类型重载运算符时 &
resp。 |
。
编辑: 书 "The C# Programming Language" (7.11) 以及 14.11.2 中带注释的 C# 标准——均通过 google 搜索结果找到-- 有一个我不理解的直接操作员调用的代码示例一定是伪代码。我试着复制那个。
顺便说一句,更难引起对 operator false()
的调用;三元条件和 if 子句总是通过调用 operator true()
来测试。似乎调用它的唯一方法是调用 operator||()
。
显式调用布尔运算符的动机是直接只定义其中一个并根据它定义另一个,这样定义总是一致的。下面是一个小示例程序,其中包含我尝试过的一些东西。有没有我错过的语法?
using System;
namespace TriviallyTrue
{
public class T
{
public static bool operator true(T t) { Console.WriteLine("In op. true"); return true; }
public static bool operator false(T t) { return true; }
}
class Program
{
static void Main(string[] args)
{
T t = new T();
// bool b = T.true(t); // Identifier expected; 'true' is a keyword
// ok, I see. Let's use the keyword syntax.
// bool b = T.@true(t); //'TriviallyTrue.T' does not contain a definition for 'true'
// That's so not true!
// oh. perhaps we need to use cast syntax, akin to invoking operator int()?
// bool b = (true)t; // ; expected
// hm. It's in T's namespace...
// bool b = (T.true)t; // Identifier expected;
// we know that.
// another cast try.
// bool b = (T.@true)t; // The type name 'true' does not exist in the type 'TriviallyTrue.T'
// ah, a type is expected. Well, the type is bool, right? But casting to bool
// doesn't work either, see below and in Main().
// bool b = (T.@bool)t; // The type name 'bool' does not exist in the type 'TriviallyTrue.T'
// well, it exists *some*what
if (t) // works
{
// Console.WriteLine("t was " + (bool)t); // Cannot convert type 'TriviallyTrue.T' to 'bool'
// That's so not true!
Console.WriteLine("t was " + (t ? "True" : "False" )); // works!
}
}
}
}
示例会话:
In op. true
In op. true
t was True
您不能在 C# 中显式调用 any 运算符方法。 operator true
和 operator false
也不例外。只是大多数运算符方法都有更直接的方法来隐式调用它们。
如果在其他情况下调用运算符方法比作为重载运算符有意义,请将其作为常规方法提供。它通常更具可读性,并且可以很好地避免您想要解决的具有多个单独实现的整个问题。
public class T
{
private bool asBoolean() { ... } // or even make it public
public static bool operator true(T t) { return t.asBoolean(); }
public static bool operator false(T t) { return !t.asBoolean(); }
}
为了完整起见,您可以实施operator false
,例如
public static bool operator false(T t) { return t ? false : true; }
但请不要这样做,除非你绝对需要。
我无法回答标题中的问题,但我认为我可以涵盖这部分
The motivation to call the boolean operators explicitly is that it would be nice to define only one of them directly and define the other one in terms of that, so that the definitions are always consistent.
不以任何方式质疑@Eric Lippert 在 post 中写的内容,当 true
或 false
中的一个在逻辑上是合乎逻辑的时,C# 有一种更简单的方法来完成所有这些另一方面,这是最常见的实际情况。无需覆盖 4 个运算符(false
、true
、&
和 |
),可以简单地提供到 bool
的单个隐式转换。
例如
public class T
{
public static implicit operator bool(T t) { return t != null; }
}
现在所有这些工作
T a = new T(), b = null;
if (a) { }
if (!a) { }
if (b) { }
if (!b) { }
if (a && b) { }
if (b && a) { }
if (a & b) { }
if (a || b) { }
if (b || a) { }
if (a | b) { }
var c1 = a ? 1 : 0;
var c2 = b ? 1 : 0;
出于好奇,我探索了 C# 中的重载运算符。有一个有趣的 post by Eric Lippert 讨论了 C++ 和 C# 中关于 operator&&
的设计决策。在 C# 中,它的重载是通过重载 operator&
加上重载布尔运算符 true
和 false
隐式定义的,这允许语言保留有时必不可少的短路语义。
玩着有点奇葩的operator true()
和false()
发现不能直接调用。相反,它们在某些需要布尔值的地方被隐式调用。据我所知,这些是直接需要 bool 的语言结构,即三元条件运算符和 if 子句,以及对 operator&&
的调用。 ||
当参数类型重载运算符时 &
resp。 |
。
编辑: 书 "The C# Programming Language" (7.11) 以及 14.11.2 中带注释的 C# 标准——均通过 google 搜索结果找到-- 有一个我不理解的直接操作员调用的代码示例一定是伪代码。我试着复制那个。
顺便说一句,更难引起对 operator false()
的调用;三元条件和 if 子句总是通过调用 operator true()
来测试。似乎调用它的唯一方法是调用 operator||()
。
显式调用布尔运算符的动机是直接只定义其中一个并根据它定义另一个,这样定义总是一致的。下面是一个小示例程序,其中包含我尝试过的一些东西。有没有我错过的语法?
using System;
namespace TriviallyTrue
{
public class T
{
public static bool operator true(T t) { Console.WriteLine("In op. true"); return true; }
public static bool operator false(T t) { return true; }
}
class Program
{
static void Main(string[] args)
{
T t = new T();
// bool b = T.true(t); // Identifier expected; 'true' is a keyword
// ok, I see. Let's use the keyword syntax.
// bool b = T.@true(t); //'TriviallyTrue.T' does not contain a definition for 'true'
// That's so not true!
// oh. perhaps we need to use cast syntax, akin to invoking operator int()?
// bool b = (true)t; // ; expected
// hm. It's in T's namespace...
// bool b = (T.true)t; // Identifier expected;
// we know that.
// another cast try.
// bool b = (T.@true)t; // The type name 'true' does not exist in the type 'TriviallyTrue.T'
// ah, a type is expected. Well, the type is bool, right? But casting to bool
// doesn't work either, see below and in Main().
// bool b = (T.@bool)t; // The type name 'bool' does not exist in the type 'TriviallyTrue.T'
// well, it exists *some*what
if (t) // works
{
// Console.WriteLine("t was " + (bool)t); // Cannot convert type 'TriviallyTrue.T' to 'bool'
// That's so not true!
Console.WriteLine("t was " + (t ? "True" : "False" )); // works!
}
}
}
}
示例会话:
In op. true
In op. true
t was True
您不能在 C# 中显式调用 any 运算符方法。 operator true
和 operator false
也不例外。只是大多数运算符方法都有更直接的方法来隐式调用它们。
如果在其他情况下调用运算符方法比作为重载运算符有意义,请将其作为常规方法提供。它通常更具可读性,并且可以很好地避免您想要解决的具有多个单独实现的整个问题。
public class T
{
private bool asBoolean() { ... } // or even make it public
public static bool operator true(T t) { return t.asBoolean(); }
public static bool operator false(T t) { return !t.asBoolean(); }
}
为了完整起见,您可以实施operator false
,例如
public static bool operator false(T t) { return t ? false : true; }
但请不要这样做,除非你绝对需要。
我无法回答标题中的问题,但我认为我可以涵盖这部分
The motivation to call the boolean operators explicitly is that it would be nice to define only one of them directly and define the other one in terms of that, so that the definitions are always consistent.
不以任何方式质疑@Eric Lippert 在 post 中写的内容,当 true
或 false
中的一个在逻辑上是合乎逻辑的时,C# 有一种更简单的方法来完成所有这些另一方面,这是最常见的实际情况。无需覆盖 4 个运算符(false
、true
、&
和 |
),可以简单地提供到 bool
的单个隐式转换。
例如
public class T
{
public static implicit operator bool(T t) { return t != null; }
}
现在所有这些工作
T a = new T(), b = null;
if (a) { }
if (!a) { }
if (b) { }
if (!b) { }
if (a && b) { }
if (b && a) { }
if (a & b) { }
if (a || b) { }
if (b || a) { }
if (a | b) { }
var c1 = a ? 1 : 0;
var c2 = b ? 1 : 0;