Is C# a=b=c; equal to b=c; a=c; whereas C++ is b=c; a=b;?
In another words, C# operator= will return the right value, is开发者_如何学编程n't it? But C++ conventionally returns left value, right?
No, the result of the assignment expression is the value assigned, not the expression on the right. So consider this:
byte a;
int b;
byte c = 10;
a = b = c; // Fails to compile
This fails to compile because although b = c
is valid, it's an expression of type int
, which then can't be assigned to a
which is of type byte
.
From the C# 4 language spec, section 7.17.1:
The result of a simple assignment expression is the value assigned to the left operand. The result has the same type as the left operand and is always classified as a value.
EDIT: Here's proof that it's the value which was assigned to b
which is used, not the value of 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
}
}
The a = b = c;
statement is equivalent to:
BType tmp = c;
b = tmp;
a = tmp;
So the value of b
isn't read afterwards (it's not equivalent to b = c; a = b;
) - so if b
were actually a property, the behaviour of the property would be irrelevant other than for side-effects. It's whatever value was used in the assignment to b
which is also used in the assignment to a
.
In this case, the assignment to b
requires a conversion from ACType
to BType
which creates a BType
with Value=50. The assignment to a
then requires a conversion from BType
to ACType
, which creates an ACType
with Value=25.
No, it works the same in both languagues: a = b = c;
works like this: a = (b = c);
. The assignment operator works right-to-left, and the value returned is the result of the assignment, which is the left-hand-side. So conceptually, a = b = c;
is the same as: b = c; a = b;
.
For C#, the assignment operators and the conditional operator (?:) are right-associative, meaning that operations are performed from right to left. For example, x = y = z is evaluated as x = (y = z). (Source)
Same for C++ (Source)
A useful tidbit about the semantics of a = b = c
is that a
will indeed receive the same value (normally c
*) that was assigned to b
, the present value of b
is not a factor.
Yes, that could be considered surprising. Consider the example:
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?
If the value passed through foo.Bar
and the mutation follows into a
, then a
would be 5. However, that is not what happens. a
and foo.Bar
receive the same value, a
does not receive the mutation from foo.Bar
. It's not directly your question, but it's interesting enough to post considering some of the comments.
*Jon Skeet had an interesting observation about types that are implicitly convertible to one another but have data loss/modification in the conversion. In this case, the value may very well not be the original value of c
, but the converted value, which may be different.
精彩评论