开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜