tags:

views:

445

answers:

6

I was writing some code today and was mid line when I alt-tabbed away to a screen on my other monitor to check something. When I looked back, ReSharper had colored the 3rd line below grey with the note "Value assigned is not used in any execution path".

var ltlName = (Literal) e.Item.FindControl("ltlName");
string name = item.FirstName;
name += 

ltlName.Text = name;

I was confused; surely this code can't compile. But it does, and it runs too. The line "name +=" has no effect (that I could tell) on the string. What's going on here?

(Visual Studio 2008, .NET 3.5)

+23  A: 

Notice that newlines are not special in C#. Because of the following line, the complete statement to the compiler is

name += ltlName.Text = name;

which is a valid statement (it assigns name to ltlName.Text, then append it to name.)

KennyTM
Exactly. That expands (roughly) out to: `ltlName.Text = name; name = name + ltlName.Text;`. *That* is equivalent to `ltlName.Text = name; name = name + name;`
Randolpho
That makes sense... I tested it with this code elsewhere:string x = `"This is a string!";MessageBox.Show(x);x +=MessageBox.Show(x);`But that also "hides" the assignment that I was missing. Thanks!
Ed Schwehm
+18  A: 

It's doing this:

name += ltlName.Text = name;

or to make it slightly clearer:

name += (ltlName.Text = name);

The result of the property setter is the value which was set, so it works a bit like this:

string tmp = name;
ltlName.Text = tmp;
name += tmp;

It's simpler to observe this when you've got different variables involved though, and just simple assignment as the final step rather than a compound assignment. Here's a complete example:

using System;

class Test
{
    public string Text { get; set; }

    static void Main()
    {
        Test t = new Test();

        string x = t.Text = "Hello";
        Console.WriteLine(x); // Prints Hello
    }
}

The simple assignment rules (section 7.17.1) are used to determine the result of the expression:

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.

So the type of ltlName.Text = name is the same type as ltlName.Text, and the value is the one that's been assigned. The fact that it's a property rather than a field or local variable doesn't change this.

Jon Skeet
Wouldn't the concatenation create something more along the lines of namename? Or does the order of operations cancel out the concat?
Joel Etherton
@Joel: No, it's still performing concatenation - the assignment version was just to make things simpler. Will edit to clarify.
Jon Skeet
@Jon Skeet - in your clarification, shouldn't that be string x += t.Text = "Hello"; (per OP) and wouldn't the result of that line print "HelloHello"?
Joel Etherton
@Joel: No. The point was to show a simpler version, where it's just doing assignment to a new variable - keeping the three aspects separate. You can't do "string x+= ..." as there's no existing value.
Jon Skeet
@Jon Skeet - oh, ok. I wasn't even thinking about that last part. I was only thinking about order of operations. As a rule I try to keep my operations fairly atomic so I don't have to worry about situations such as this.
Joel Etherton
Thanks for the detailed explanation! I'm kind of annoyed at myself that I didn't notice this myself, but that's why we have StackOverflow.
Ed Schwehm
It is perhaps worth noting that code that does multiple assignments in one expression like this is hard to read and should generally be avoided. (The fact that it was confusing enough to have a question about it posted is evidence of that!)
Eric Lippert
+5  A: 

In C#, newlines don't terminate statements - only semicolons do. So the following line of code is executing:

name += ltlName.Text = name;
froadie
+1  A: 

Because whitespace is irrelevant in C#, line 3, 4 and 5 form one statement:

name += ltlName.Text = name;
Jesse Dhillon
A: 

It is affecting the string, but not until after the string is used to affect the literal on the display. As KennyTM pointed out, both lines form a single statement. Unlike VB, the carriage return doesn't end a statement in C#. The semicolon does. So what's happening here is the string is being set to the literal, and the result of that operation ("true" perhaps? or just the string itself? I don't remember) is being appended to the string.

David
+1  A: 

As expected, the result is name concatenated to itself. So you get "namename".

obj.Text is just a property, so the line ends up converting to

//name += obj.Text = name;
obj.setText(name);
name += obj.Text;

Full source below

public class Program
{
    public static void Main(string[] args)
    {
        MyClass obj = new MyClass();
        string name = "name";
        name += obj.Text = name;
        Console.Write(name); //prints namename
    }
}
JonWillis