【问题标题】:&& operator overloading and assignments in C# - Clarification?C# 中的 && 运算符重载和赋值 - 澄清?
【发布时间】:2015-08-14 11:43:41
【问题描述】:

以下this very interesting issue 源自this 问题-

我想退一步(去掉动态环境):

看这段代码:(a variant of this one)

void Main()
{
    int a;
     int b = 100;
    Console.WriteLine(X.M(1, out a));

}

public class X
{
    public  int H=0;

    public static X M(int x, out int y)
    {
        Console.WriteLine("x = "+x);
        y = x;
        return new X(x);
    }

    public X(){}

    public X(int h)
    {
        H=h;
    }

    public static bool operator false(X x)     {Console.WriteLine("in false operator for "+ x.H); return true; }
    public static bool operator true(X x)      {Console.WriteLine("in true operator for "+ x.H); return true; }
    public static X operator &(X a, X b)       {Console.WriteLine("in & operator for "+ a.H+","+b.H);   return new X(); }
    public static implicit operator bool (X x) {Console.WriteLine("in bool operator for "+ x.H);return true; }
}

结果是:

x = 1
in bool operator for 1
True

这是明白的:

  • x = 1 来自方法本身(使用Console.Writeline
  • in bool operator for 1 是从 XBool 的隐式运算符 (所以 - Console.WriteLine 将整个表达式视为 Console.Writeline(bool)
  • 最后一个“True”来自operator bool (X x)中的“return true”

好的 - 所以让我们改变

Console.WriteLine(X.M(1, out a));

Console.WriteLine(X.M(1, out a) &&  X.M(2, out b));

现在 - 结果是:

x = 1
in false operator for 1
in bool operator for 1
True

2 个问题

  1. 为什么这个in false operator for 1 会执行?我看不出有任何理由让false 出现在这里。

  2. 我可以理解为什么 X.M(1, out a) && X.M(2, out b) 中的右侧部分只有在左侧部分是 false 时才会执行 - 但我还是不明白左侧部分怎么可能是假的。它确实返回true(根据我的第一个代码)

注意

我已经多次阅读帖子中的答案:

乔恩说:

第二个 && 是两个布尔表达式之间的普通 && - 因为 Nop 返回 bool,并且没有 &(X, bool) 运算符...但是有一个 从 X 到 bool 的转换。

所以它更像是:

bool first = X.M(1, out a) && X.M(2, out b);
if (first && Nop(a, b))

尽管只有 && 的第一个操作数是 评估...所以 b 真的没有被分配。

我还是不明白:“第一个是 true(????) 尽管只计算了 && 的第一个操作数”

【问题讨论】:

  • 如果false()操作符返回true,则表示该操作返回false("is x false? yes it is (return true;)")!这不是operator bool()
  • 调用false() 运算符来短路&&... 他们本可以调用true() 运算符,但例如msdn&& 的定义: 除了如果 x 为假,不计算 y
  • 参见stackoverflow.com/a/5203515/613130&& 被定义为短路操作符; 如果第一个操作数计算为假,则要求在此处短路而不计算右侧。
  • @xanatos 是的。但这就是我看不到第一个操作数在哪里获得错误值的问题。
  • 因为&&运算符被翻译成if(not operator false(left expression))然后计算右表达式

标签: c#


【解决方案1】:

首先,不要忘记这是故意奇怪的代码,用于查找极端情况。如果你在真正的程序中发现了这样的行为类型,请找到作者并与他们保持沉默。

我还是不明白:“虽然只有 && 的第一个操作数被求值,但第一个是真的(????)”

是的,因为在操作数不是 bool 的情况下处理 && 操作数的方式。它在 C# 规范的第 7.12.2 节中指定:

操作x && y 被评估为T.false(x) ? x : T.&(x, y),其中T.false(x)T 中声明的operator false 的调用,T.&(x, y)& 中选定运算符的调用。换句话说,首先评估x,然后在结果上调用operator false,以确定x 是否肯定为假。然后,如果x 肯定为假,则运算结果是先前为x 计算的值。否则,将评估y,并根据先前为x 计算的值和为y 计算的值调用选定的operator &,以生成操作结果。

所以,按顺序:

  • 调用X.M(1, out a) 以获得结果 - 暂时称它为op1
  • 接下来调用X.false(op1),并返回true
  • 那么通过上面,X.M(1, out a) && X.M(2, out b) 表达式的结果是op1
  • 接下来,调用从op1bool 的转换值,并返回true。这是由于Console.WriteLine 的过载解决方案。

回答您的具体困惑:

但我还是看不出左边部分怎么可能是假的。它确实返回真(根据我的第一个代码)

它返回一个有点矛盾的值——它是false,因为false 运算符返回true,但它是true,因为转换为bool 返回true。一旦你明白是false运算符返回的值决定了是否计算&&的第二个操作数,就应该清楚了。

【讨论】:

  • 但是为什么它会调用operator bool?在我解释规范时,&& 操作的结果应该只是operator & 调用的结果。
  • @erikkallen:这取决于上下文:) 在Console.WriteLine 调用的上下文中,这是因为有一个接受bool 的重载,这比接受object 的重载更具体。在 Neal Gafter 程序的原始上下文中,这是因为结果将用作 another && 表达式中的第一个操作数,其中右侧表达式的类型为 bool
  • 感谢您的解释。我必须说,我很惊讶它会使用隐式运算符来定位更具体的重载。
猜你喜欢
  • 2013-03-30
  • 2016-08-30
  • 1970-01-01
  • 1970-01-01
  • 2012-04-22
  • 2015-06-01
  • 2011-01-27
  • 2011-05-31
  • 2012-08-17
相关资源
最近更新 更多