可以显式调用“运算符 true()”吗?什么时候用于转换为布尔值


出于

好奇,我探索了 C# 中的重载运算符。Eric Lippert有一篇有趣的文章,讨论了C++和C#中关于operator&&的设计决策。在C#中,它的重载是通过重载operator&加上重载布尔运算符truefalse来隐式定义的,这允许语言保留有时基本的短路语义。

玩弄有点异国情调的operator true()false()我发现我无法直接打电话给他们。相反,它们在某些需要布尔值的地方被隐式调用。据我所知,这些是直接需要布尔值的语言结构,即三元条件运算符和 if 子句,加上对 operator&& resp 的调用。 ||当参数类型具有重载运算符时& | .

编辑:《C#编程语言》(7.11)一书以及14.11.2中带注释的C#标准 - 都是通过谷歌搜索结果找到的 - 有一个带有直接运算符调用的代码示例,我不明白一定是伪代码。我试图复制这一点。

顺便说一句,引发对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

我无法回答标题中的问题,但我想我可以涵盖这部分

显式调用布尔运算符的动机是,最好只直接定义其中一个并据此定义另一个运算符,以便定义始终保持一致。

在不以任何方式质疑Lippert@Eric写的内容的情况下,当truefalse之一在逻辑上与另一个相反时,C#有一种更简单的方法来完成所有这些工作,这是最常见的实际情况。与其覆盖 4 个运算符(falsetrue&|),不如简单地提供对 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# 中显式调用任何运算符方法。 operator trueoperator 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; }

但请不要这样做,除非你绝对需要。

最新更新