换句话说,C#的operator=会返回右值,对吧?但是传统的C++会返回左值,对吗?
不是的,赋值表达式的结果是被赋值的值,而不是右侧的表达式。因此请考虑以下代码:
byte a;
int b;
byte c = 10;
a = b = c; // Fails to compile
这段代码编译失败的原因是,尽管 b=c
是合法的表达式,但它是一个类型为 int
的表达式,无法被赋值给类型为 byte
的变量 a
。
这里引用了 C# 4 语言规范,第 7.17.1 节:
简单赋值表达式的结果是被赋值给左操作数的值。该结果与左操作数具有相同的类型,并始终被分类为值。
编辑后:以下是证明所赋值的是 b
的值而不是 c
的值的证据:
using System;
class ACType
{
public int Value { get; set; }
public static implicit operator BType(ACType ac)
{
return new BType { Value = ac.Value / 2 };
}
}
class BType
{
public int Value { get; set; }
public static implicit operator ACType(BType b)
{
return new ACType { Value = b.Value / 2 };
}
}
class Test
{
static void Main()
{
ACType a, c;
BType b;
c = new ACType { Value = 100 };
a = b = c;
Console.WriteLine(a.Value); // Prints 25
}
}
a = b = c;
语句等同于:
BType tmp = c;
b = tmp;
a = tmp;
所以,b
的值在此后并没有被“读取”(它与 b = c; a = b;
不等价),因此如果 b
实际上是一个属性,属性的行为除了副作用之外都是无关紧要的。在对 a
赋值时使用的是同样用于对 b
赋值时使用的那个值。b
的赋值需要将 ACType
转换为 BType
,从而创建一个 Value=50 的 BType
。然后对 a
的赋值需要将 BType
转换为 ACType
,从而创建一个 Value=25 的 ACType
。a = b = c
的总体值可能看起来与这里的任何变量的值都不一样,这些变量可能根本不相等。其中一部分我知道,一部分是你帮助我学习的,而大部分我希望在我的编码活动中永远不必考虑。 - Anthony Pegramb
的值。我现在正在想一个例子。 - Jon Skeet关于 a = b = c
的语义,一个有用的提示是,a
确实会接收到与 b
赋值相同的值(通常是 c*),而 b
目前的值并不影响。
是的,这可能令人惊讶。考虑以下示例:
class Foo
{
private int _bar;
public int Bar
{
get { return _bar; }
set { _bar = value + 1; }
}
}
...
Foo foo = new Foo();
int a, c;
c = 4;
a = foo.Bar = c; // is 'a' 4 or 5?
foo.Bar
传递的值并且变异进入 a
,则 a
将是 5。然而,事实并非如此。 a
和 foo.Bar
收到相同的值,a
没有收到来自 foo.Bar
的变异。这不是直接回答问题,但考虑到一些评论,这非常有趣。
c
的原始值,而是转换后的值,可能会有所不同。c
相同的值。想象一下两种类型彼此具有隐式转换但会丢失数据,其中 a
和 c
是一种类型,而 b
是另一种类型。将从 c
的类型转换为 b
的类型,然后再将其转换回 a
的类型。 - Jon Skeet
a = c; b = c;
(写在两行上)甚至避免了考虑任何可能的歧义,并且明显表明有两个赋值。 - Justin=
表示两个赋值?(顺便说一下,比较应该是b = c; a = b
。) - Kirk Woll