• Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
  • Advertising & Talent Reach devs & technologists worldwide about your product, service or employer brand
  • OverflowAI GenAI features for Teams
  • OverflowAPI Train & fine-tune LLMs
  • Labs The future of collective knowledge sharing
  • About the company Visit the blog

Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Get early access and see previews of new features.

Why do assignment statements return a value?

This is allowed:

To my understanding, assignment s = ”Hello”; should only cause “Hello” to be assigned to s , but the operation shouldn’t return any value. If that was true, then ((s = "Hello") != null) would produce an error, since null would be compared to nothing.

What is the reasoning behind allowing assignment statements to return a value?

Michael Petrotta's user avatar

  • 49 For reference, this behavior is defined in the C# spec : "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." –  Michael Petrotta Commented Sep 27, 2010 at 19:41
  • 1 @Skurmedel I am not the downvoter, I agree with you. But maybe because it was thought to be a rhetorical question? –  jsmith Commented Sep 27, 2010 at 19:48
  • 1 In pascal/delphi assignment := returns nothing. i hate it. –  Andrey Commented Sep 27, 2010 at 19:51
  • 20 Standard for languages in the C branch. Assignments are expressions. –  Hans Passant Commented Sep 27, 2010 at 19:52
  • "assignment ... should only cause “Hello” to be assigned to s, but the operation shouldn’t return any value" -- Why? "What is the reasoning behind allowing assignment statements to return a value?" -- Because it's useful, as your own examples demonstrate. (Well, your second example is silly, but while ((s = GetWord()) != null) Process(s); is not). –  Jim Balter Commented Jul 23, 2015 at 21:40

14 Answers 14

To my understanding, assignment s = "Hello"; should only cause "Hello" to be assigned to s, but the operation shouldn’t return any value.

Your understanding is 100% incorrect. Can you explain why you believe this false thing?

First off, assignment statements do not produce a value. Assignment expressions produce a value. An assignment expression is a legal statement; there are only a handful of expressions which are legal statements in C#: awaits of an expression, instance construction, increment, decrement, invocation and assignment expressions may be used where a statement is expected.

There is only one kind of expression in C# which does not produce some sort of value, namely, an invocation of something that is typed as returning void. (Or, equivalently, an await of a task with no associated result value.) Every other kind of expression produces a value or variable or reference or property access or event access, and so on.

Notice that all the expressions which are legal as statements are useful for their side effects . That's the key insight here, and I think perhaps the cause of your intuition that assignments should be statements and not expressions. Ideally, we'd have exactly one side effect per statement, and no side effects in an expression. It is a bit odd that side-effecting code can be used in an expression context at all.

The reasoning behind allowing this feature is because (1) it is frequently convenient and (2) it is idiomatic in C-like languages.

One might note that the question has been begged: why is this idiomatic in C-like languages?

Dennis Ritchie is no longer available to ask, unfortunately, but my guess is that an assignment almost always leaves behind the value that was just assigned in a register. C is a very "close to the machine" sort of language. It seems plausible and in keeping with the design of C that there be a language feature which basically means "keep on using the value that I just assigned". It is very easy to write a code generator for this feature; you just keep on using the register that stored the value that was assigned.

Eric Lippert's user avatar

  • 1 Wasn't aware that anything which returns a value ( even instance construction is considered an expression ) –  user437291 Commented Sep 27, 2010 at 20:56
  • 9 @user437291: If instance construction wasn’t an expression, you couldn’t do anything with the constructed object — you couldn’t assign it to something, you couldn’t pass it into a method, and you couldn’t call any methods on it. Would be pretty useless, wouldn’t it? –  Timwi Commented Sep 27, 2010 at 22:45
  • 1 Changing a variable is actually "just" a side effect of the assignment operator, which, creating an expression, yields a value as its primary purpose. –  mk12 Commented Aug 24, 2012 at 22:08
  • 2 "Your understanding is 100% incorrect." -- While the OP's use of English isn't the greatest, his/her "understanding" is about what should be the case, making it an opinion, so it isn't the sort of thing than can be "100% incorrect". Some language designers agree with the OP's "should", and make assignments have no value or otherwise ban them from being subexpressions. I think that's an overreaction to the = / == typo, which is easily addressed by disallowing using the value of = unless it is parenthesed. e.g., if ((x = y)) or if ((x = y) == true) is allowed but if (x = y) is not. –  Jim Balter Commented Jul 23, 2015 at 21:01
  • 1 @BobKaufman: Fun fact, JavaScript still does that . Never do this, but in JavaScript you can say x=eval("if(whatever)y=2; else z=3;"); and x will be either 2 or 3 . eval is pure unmitigated evil . –  Eric Lippert Commented Aug 29, 2018 at 18:55

Haven’t you provided the answer? It’s to enable exactly the kinds of constructs you have mentioned.

A common case where this property of the assignment operator is used is reading lines from a file...

Timwi's user avatar

  • 1 +1 This has to be one of the most practical uses of this construct –  Mike Burton Commented Sep 27, 2010 at 20:40
  • 13 I really like it for really simple property initializers, but you have to be careful and draw your line for "simple" low for readability: return _myBackingField ?? (_myBackingField = CalculateBackingField()); A lot less chaff than checking for null and assigning. –  Tom Mayfield Commented Sep 27, 2010 at 22:02

My favorite use of assignment expressions is for lazily initialized properties.

Nathan Baulch's user avatar

  • 6 Which is why so many people have suggested the ??= syntax. –  configurator Commented Sep 10, 2011 at 19:39
  • 2 Now that ??= is there, you can still use it with an assignment expression, makes it even easier: public string Name => this.name ??= ExpensiveNameGeneratorMethod(); –  jsabrooke Commented Oct 14, 2020 at 8:52
  • Sad that ??= is only available for .NET Core :( –  Alex from Jitbit Commented Mar 29, 2021 at 10:29

For one, it allows you to chain your assignments, as in your example:

For another, it allows you to assign and check a result in a single expression:

Both are possibly dubious reasons, but there are definitely people who like these constructs.

Michael Burr's user avatar

  • 6 +1 Chaining isn't a critical feature but it's nice to see it "just works" when so many things don't. –  Mike Burton Commented Sep 27, 2010 at 20:41
  • +1 for chaining also; I'd always thought of that as a special case that was handled by the language rather than the natural side effect of "expressions return values". –  Caleb Bell Commented Nov 30, 2011 at 17:59
  • 2 It also allows you to use assignment in returns: return (HttpContext.Current.Items["x"] = myvar); –  Serge Shultz Commented Mar 12, 2013 at 9:48

Aside from the reasons already mentioned (assignment chaining, set-and-test within while loops, etc), to properly use the using statement you need this feature:

MSDN discourages declaring the disposable object outside of the using statement, as it will then remain in scope even after it has been disposed (see the MSDN article I linked).

Martin Törnwall's user avatar

  • 4 I don't think this is really assignment chaining per se. –  kenny Commented Sep 27, 2010 at 20:53
  • 1 @kenny: Uh... No, but I never claimed it was, either. As I said, aside from the reasons already mentioned -- which includes assignment chaining -- the using statement would be a lot more difficult to use were it not for the fact that the assignment operator returns the result of the assignment operation. This isn't really related to assignment chaining at all. –  Martin Törnwall Commented Sep 27, 2010 at 21:32
  • 1 But as Eric noted above, "assignment statements do not return a value". This is actually just language syntax of the using statement, proof to that is that one can't use an "assignment expression" in a using statement. –  kenny Commented Sep 27, 2010 at 22:31
  • 2 @kenny: Actually, one can use either a definition-and-assignment statement, or any expression in using . All of these are legal: using (X x = new X()) , using (x = new X()) , using (x) . However, in this example, the contents of the using statement is a special syntax that doesn't rely at all on assignment returning a value - Font font3 = new Font("Arial", 10.0f) is not an expression and is not valid in any place that expects expressions. –  configurator Commented Sep 10, 2011 at 19:37
  • 1 " to properly use the using statement you need this feature" -- No, you most certainly do not. "without the language having general support for assignment expressions returning a value" -- why are you talking about assignment expressions? This is a variable definition with an initializer -- which is not an expression. "That would, in my eyes, be terribly inconsistent though." -- Your example of using (definition) completely contradicts you ... there's nowhere else such a construction can be used. –  Jim Balter Commented Jul 23, 2015 at 21:18

I'd like to elaborate on a specific point Eric Lippert made in his answer and put the spotlight on a particular occasion that hasn't at all been touched upon by anyone else. Eric said:

[...] an assignment almost always leaves behind the value that was just assigned in a register.

I'd like to say that the assignment will always leave behind the value we tried to assign to our left operand. Not just "almost always". But I don't know because I haven't found this issue commented in the documentation. It might theoretically be a very effective implemented procedure to "leave behind" and not reevaluate the left operand, but is it efficient?

'Efficient' yes for all the examples so far constructed in the answers of this thread. But efficient in the case of properties and indexers that use get- and set accessors? Not at all. Consider this code:

Here we have a property, which isn't even a wrapper for a private variable. Whenever called upon he shall return true, whenever one tries to set his value he shall do nothing. Thus whenever this property is evaluated, he shall be truthy. Let's see what happens:

Guess what it prints? It prints Unexpected!! . As it turns out, the set accessor is indeed called, which does nothing. But thereafter, the get accessor is never called at all. The assignment simply leaves behind the false value we tried to assign to our property. And this false value is what the if statement evaluates.

I'll finish off with a real world example that got me researching this issue. I made an indexer which was a convenient wrapper for a collection ( List<string> ) that a class of mine had as a private variable.

The parameter sent to the indexer was a string, which was to be treated as a value in my collection. The get accessor would simply return true or false if that value existed in the list or not. Thus the get accessor was another way to use the List<T>.Contains method.

If the indexer's set accessor was called with a string as an argument and the right operand was a bool true , he would add that parameter to the list. But if the same parameter was sent to the accessor and the right operand was a bool false , he would instead delete the element from the list. Thus the set accessor was used as a convenient alternative to both List<T>.Add and List<T>.Remove .

I thought I had a neat and compact "API" wrapping the list with my own logic implemented as a gateway. With the help of an indexer alone I could do many things with a few set of keystrokes. For instance, how can I try to add a value to my list and verify that it's in there? I thought this was the only line of code necessary:

But as my earlier example showed, the get accessor which is supposed to see if the value really is in the list wasn't even called. The true value was always left behind effectively destroying whatever logic I had implemented in my get accessor.

ardila's user avatar

  • Very interesting answer. And it's made me think positively about test-driven development. –  Elliot Commented Feb 12, 2015 at 15:04
  • 1 While this is interesting, it's a comment upon Eric's answer, not an answer to the OP's question. –  Jim Balter Commented Jul 23, 2015 at 21:25
  • I wouldn't expect an attempted assignment expression to first get the value of the target property. If the variable is mutable, and the types match, why would it matter what the old value was? Just set the new value. I'm not a fan of assignment in IF tests though. Is it returning true because the assignment was successful, or it's some value e.g. a positive integer that is coerced to true, or because you are assigning a boolean? Regardless of the implementation, the logic is ambiguous. –  Davos Commented Sep 1, 2016 at 11:42

If assignment didn't return a value, the line a = b = c = 16 wouldn't work either.

Also being able to write things like while ((s = readLine()) != null) can be useful sometimes.

So the reason behind letting assignment return the assigned value, is to let you do those things.

sepp2k's user avatar

  • Nobody's mentioned disadvantages - I came here wondering why assignments couldn't return null, in order that the common assignment vs comparison bug 'if (something = 1){}' would fail to compile rather than always returning true. I now see that that would create... other issues! –  Jon Commented Mar 11, 2014 at 15:35
  • 1 @Jon that bug could be easily prevented by disallowing or warning about = occurring in an expression that isn't parenthesized (not counting the parens of the if/while statement itself). gcc gives such warnings and has thereby essentially eliminated this class of bugs from C/C++ programs that are compiled with it. It's a shame that other compiler writers have paid so little attention to this and several other good ideas in gcc. –  Jim Balter Commented Jul 23, 2015 at 21:10

I think you're misunderstanding how the parser is going to interpret that syntax. The assignment will be evaluated first , and the result will then be compared to NULL, i.e. the statement is equivalent to:

As others have pointed out, the result of an assignment is the assigned value. I find it hard to imagine the advantage to having

((s = "Hello") != null)

not be equivalent...

Dan J's user avatar

  • While you are right from a practical sense that your two lines are equivalent your statement that the assignment is not returning a value is not technically true. My understanding is that the result of an assignment is a value (per the C# spec), and in that sense is no different from say the addition operator in an expression like 1 + 2 + 3 –  Steve Ellinger Commented Sep 27, 2010 at 20:25

I think the main reason is the (intentional) similarity with C++ and C. Making the assigment operator (and a lot of other language constructs) behave like their C++ counterparts just follows the principle of least surprise, and any programmer coming from another curly-bracket language can use them without spending much thought. Being easy to pick up for C++ programmers was one of the main design goals for C#.

tdammers's user avatar

For the two reasons you include in your post 1) so you can do a = b = c = 16 2) so you can test if an assignment succeeded if ((s = openSomeHandle()) != null)

JamesMLV's user avatar

The fact that 'a++' or 'printf("foo")' may be useful either as a self-contained statement or as a part of a larger expression means that C has to allow for the possibility that expression results may or may not be used. Given that, there's a general notion that expressions which might usefully 'return' a value may as well do so. Assignment chaining can be slightly "interesting" in C, and even more interesting in C++, if all the variables in question do not have precisely the same type. Such usages are probably best avoided.

supercat's user avatar

An extra advantage I don't see given in the answers here, is that the syntax for assignment is based on arithmetic.

Now x = y = b = c = 2 + 3 means something different in arithmetic than a C-style language; in arithmetic its an assertion, we state that x is equal to y etc. and in a C-style language it's an instruction that makes x equal to y etc. after it is executed.

This said, there's still enough relation between the arithmetic and the code that it doesn't make sense to disallow what is natural in the arithmetic unless there's a good reason. (The other thing that C-style languages took from the use of the equals symbol is the use of == for equality comparison. Here though because the right-most == returns a value this sort of chaining would be impossible.)

Jon Hanna's user avatar

  • @JimBalter I wonder whether, in five years time, you might actually make an argument against. –  Jon Hanna Commented Jul 23, 2015 at 21:27
  • @JimBalter no, your second comment is actually a counter argument, and a sound one. My thinking retort was because your first comment was not. Still, when learning arithmetic we learn a = b = c means that a and b and c are the same thing. When learning a C style language we learn that after a = b = c , a and b are the same thing as c . There's certainly a difference in semantics, as my answer itself says, but still when as a child I first learned to program in a language which did use = for assignment but didn't allow a = b = c this seemed unreasonable to me, though … –  Jon Hanna Commented Jul 23, 2015 at 22:01
  • … unavoidable because that language also used = for equality comparison, so in that a = b = c would have to mean what a = b == c means in C-style languages. I found the chaining allowed in C a lot more intuitive because I could draw an analogy to arithmetic. –  Jon Hanna Commented Jul 23, 2015 at 22:04

Another great example use-case, I use this all the time:

jazzcat's user avatar

I like using the assignment return value when I need to update a bunch of stuff and return whether or not there were any changes:

Be careful though. You might think you can shorten it to this:

But this will actually stop evaluating the or statements after it finds the first true. In this case that means it stops assigning subsequent values once it assigns the first value that is different.

See https://dotnetfiddle.net/e05Rh8 to play around with this

Luke Kubat's user avatar

Your Answer

Reminder: Answers generated by artificial intelligence tools are not allowed on Stack Overflow. Learn more

Sign up or log in

Post as a guest.

Required, but never shown

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy .

Not the answer you're looking for? Browse other questions tagged c# syntax or ask your own question .

  • Featured on Meta
  • We spent a sprint addressing your requests — here’s how it went
  • Upcoming initiatives on Stack Overflow and across the Stack Exchange network...
  • Policy: Generative AI (e.g., ChatGPT) is banned
  • The [lib] tag is being burninated
  • What makes a homepage useful for logged-in users

Hot Network Questions

  • How is the result of this integral obtained by the function `Integrate`?
  • Are Dementors found all over the world, or do they only reside in or near Britain?
  • In equation (3) from lecture 7 in Leonard Susskind’s ‘Classical Mechanics’, should the derivatives be partial?
  • Is this heat damage to spotted dead-nettle?
  • Use multiple image texture frames in Geometry Nodes
  • How would I say the exclamation "What a [blank]" in Latin?
  • Are there alternatives to alias I'm not aware of?
  • Logical AND (&&) does not short-circuit correctly in #if
  • Does concentrating on a different spell end a concentration spell?
  • Did the BBC censor a non-binary character in Transformers: EarthSpark?
  • Predictable Network Interface Names: ensX vs enpXsY
  • Equivariant Smith normal form?
  • mirrorlist.centos.org no longer resolve?
  • How to maintain dependencies shared among microservices?
  • Can you help me to identify the aircraft in a 1920s photograph?
  • Geometry question about a six-pack of beer
  • I want to leave my current job during probation but I don't want to tell the next interviewer I am currently working
  • Using generative AI at work
  • Is there an economic incentive to use p2wsh over p2tr?
  • Why should I meet my advisor even if I have nothing to report?
  • What to do if you disagree with a juror during master's thesis defense?
  • A chess engine in Java: generating white pawn moves - take II
  • Is it possible to complete a Phd on your own?
  • Times of a hidden order

c assignment return value

IMAGES

  1. return statement in C/C++ with Examples

    c assignment return value

  2. Main Function Return Value

    c assignment return value

  3. Return Statement in C

    c assignment return value

  4. C++ Return by Reference

    c assignment return value

  5. C++ Tutorial

    c assignment return value

  6. function with return value

    c assignment return value

VIDEO

  1. P3

  2. NPTEL Problem Solving Through Programming In C Week 0 Quiz Assignment Solution

  3. Assignment Operator in C Programming

  4. NPTEL Problem Solving through Programming in C ASSIGNMENT 6 ANSWERS 2024

  5. Assignment with a Returned Value (Basic JavaScript) freeCodeCamp tutorial

  6. Returning 2 values from a function in C programming Language

COMMENTS

  1. c

    An assignment expression has the value of the left operand after the assignment. It's to allow things like this: a = b = c; (although there's some debate as to whether code like that is a good thing or not.) Incidentally, this behaviour is replicated in …