Chaining simple assignments is not so simple

UPDATE: I interrupt this episode of FAIC with a request from my friend and colleague Lucian, from the VB team, who wonders whether it is common in C# to take advantage of the fact that assignment expressions are expressions. The most common usage of this pattern is the subject of this blog entry: the fact that "chained" assignment works at all is a consequence of the fact that assignments are expressions, not statements. There are other uses too; one could imagine something like "return this.myField = x;" as a short cut for "this.myField = x; return this.myField;" -- perhaps we are performing some computation and then recording the results for use later. Or perhaps we've got something like myNonNullableString = (myNullableString = Foo()) ?? "<null>"; -- there are any number of ways this idiom could be used.

I do not use this idiom myself; I'm of the opinion that side effects such as assignments are best represented by putting each in a statement of its own, rather than as something embedded in a larger expression. My question for you is: do you use assignments as expressions? If so, how and why? Note that I am looking for mundane, "real world" examples of this pattern, not clever ideas about how this could in theory be used. If you've got one, please leave it in the comments and I'll pass it along to Lucian. Thanks!


Today I examine another myth about C#. Consider the following code:

a = b = c;

This is legal; you can make arbitrarily long chains of simple assignments. This pattern is most often seen in something like

int i, j, k;
i = j = k = 123;

I often hear that this works “because assignment is right-associative and results in the value of the right-hand side”.

Well, that’s half true. It is right-associative; obviously this has to be equivalent to

i = (j = (k = 123)));

It doesn’t make any sense to parenthesize it from the left. Now, in this particular example, the statement is true, but in general it is not. The result of the simple assignment operator is not the value of the right hand side:

const int x = 10;
short y;
object z;
z = y = x;

This prints “System.Int16”, not “System.Int32”. The value of the right-hand side of “y = x” is clearly an int, but we do not assign a reference to a boxed int to z, we assign a reference to a boxed short!

So then is the correct statement “… results in the value of the left-hand side”?

Nope, that’s not right either, and we can prove it.

class C
  private string x;
  public string X {
    get { return x ?? ""; }
    set { x = value; } }
  static void Main()
    C c = new C();
    object z;
    z = c.X = null;
    System.Console.WriteLine(z == null);
    System.Console.WriteLine(c.X == null);

This prints “True / False” – the result of the assignment operator is not the value of the left-hand-side. The value of the left hand side is the empty string but the value of the operator is null.

Heck, the left hand side need not even have a value. Write-only properties are weird and rare, but legal; if there were no getter then the left hand side c.X would not have a value!

The correct statement should now be pretty easy to deduce: the result of the simple assignment operator is the value that was assigned to the left-hand side.


Comments (46)
  1. Felipe Fujiy says:


    const int x = 10;

    short y;

    object z;

    z = y = x;


    Shoud work them

  2. pete.d says:

    Maybe there’s some compiler-internal aspect here that is more interesting, but I take issue with the statement that "The value of the right-hand side of “y = x” is clearly an int".

    In particular, I expect the value of the right-hand side of an assignment expression to be exactly the thing that is stored into the left-hand side.  Thus, the right-hand side is _not_ "clearly an int".  It seems clear that, given the destination of the assignment operation, that the type of the right-hand side must be a short.

    True, there is implicit type conversion going on in order to allow that.  Likewise this example:

     string str = "Hello";

     object obj;

     obj = str;

    The right-hand side of the assignment must be System.Object, because that’s the type of the destination.  But of course, we can implicitly convert System.String to System.Object without extra code.

    As I said, perhaps to the compiler, the right-hand side really is some other type, and there’s something about the internals of the compilation process where it’s important to state unequivocally that the type isn’t necessarily that of the destination.  But from the point of view of the programmer without intimate knowledge of the inner workings of the compiler, it’s not clear at all to me that we must consider the type of the right-hand side to be other than that of the destination type.

  3. Pete, I have to disagree with your post. Consider (All "T"’s are types…)

    T1 a = value;

    T3 c = a;

    This can be equivilant to

    T1 a = value;

    T3 F1(T1 arg) {…} Converts T1 to T3

    T3 c = F1(a);

    Or Even

    T1 a = value;

    T2 F1(T1 arg) {…} Converts T1 to T2

    T3 F2(T2 arg) {…} Converts T2 to T3

    T2 b = F1(a);

    T3 c = F1(b);

    In the aove sample, it is clear that the contents of "a" are of type T1, and that the contents of "c" are of type T3.

    By logical extension, the RHS of the original statement is also of type T1 and only of type T1. Remember we are looking at the Right Side ONLY, ignoring any conversions (as are explicitly shown in the other samples) and NOT looking at the assignment statement.

    As a result, there is a world of difference between "the type of the RHS" and the "type that is assigned to the LHS" (which is NOT necessarily the declared type of the LHS!!!!

    Hopefully this clears things up…

  4. Robert Davis says:

    Interesting, of course this leads to the following unexpected behavior:

    class Foo


      public int Bar { get { return 20; } set { } }


    Foo f = new Foo();

    int baz = f.Bar = 10;

    Console.WriteLine(baz); // Prints 10;

  5. Grico says:

    @Robert Davis

    I disagree. What would be completely unexpected is that baz equals 20. If I have a chained assignment the last thing I’d expect to see is that the result of said expression is a value that doesn’t even show up.

    The unexpected behaviour there is simply caused by a wrong property setter. As a matter of fact, shouldn’t the compiler flag a empty setter property at least as a warning?

  6. Robert Davis says:


    I disagree, properties are a different animal than fields/local variables.

    Essentially Eric’s post shows that

    int baz = f.Bar = 10;

    has an entirely different effect than

    f.Bar = 10;

    int baz = f.Bar;

    which I think most would find unexpected.

    Also, nothing wrong with an empty setter, especially if you’re implementing an interface or sub-classing.

  7. Grico says:

    I dont see how empty setters could help subclassing or implementing an interface. The way I see it if your setter doesnt do anything then dont implement one. If you need to because you are impelementing an interface but the best choice is to leave it empty then something is wrong with your design. As a last resort I’d throw a not implemented / not supproted exception. A setter that doesnt do anything is misleading and will only lead to unexpected behaviour as in your example.

    And yes of course that

    int baz = f.Bar = 10;

    has an entirely different effect than

    f.Bar = 10;

    int baz = f.Bar;

    one is a chained assignment, the other one isnt. The point is that intuitively when I see a chained assignment I expect everything to end up with the same value. Thats the whole point of a chained assignment and  C#’s implementation does a great job in trying to do exactly that. By passing on the value assigned to the left hand side intermediate property getters are always skipped. This is great because you can never ensure that the getter will return the same value that was passed to the setter which defeats the purpose of a chained assignment.

    My gripe with empty setter doesnt really apply here at all now that I think about it, as the unexpected behaviour would apply anytime we have a property that gets a value that is different to the value that is passed to its setter.

  8. Jim L says:

    Ouch. I guess I’m glad it works this way. How batty would you go trying to figure this out otherwise…

    z = c.X = null;

    //bunches of code

    if (z == null)


    //why do I never get here?


  9. pete.d says:

    Sorry David…you claim to disagree, but I don’t see how your example demonstrates that.  If anything, you are simply proving my point, by pointing out that an assignment is _equivalent_ to converting to the necessary type and then copying the resulting value.

    The fact that when assigning “a” to “c” that conversion isn’t explicitly in code doesn’t mean it’s not there.  The compiler does implicit conversions all the time in all sorts of situations.

    In fact, Eric’s closing statement – “the result of the simple assignment operator is the value that was assigned to the left-hand side” – is IMHO simply a reiteration of my point.  That is, the value of the right-hand side of the assignment operator is in fact the thing that is assigned to the left-hand side, _after_ any necessary conversion.

    I realize it’s a semantic argument, at least absent any specific compiler implementation details.  Hence my equivocation on that point in my first reply.  But it’s my opinion that stating from the outset that “clearly” the right-hand side is _not_ the same type as the destination of the assignment is just a straw man, in that is assumes something that I don’t take to be true.  That assertion is not at all obviously clear to me; it’s entirely dependent on how you interpret the assignment operation.

    I happen to interpret the assignment operation as a simple copy from one place to another, with any type conversion required taking place before the actual operation.  In this respect, it’s as if the assignment operator worked like every other overloadable operator, where the assignment operator itself doesn’t do any work until the compiler has resolved all the necessary type conversions.  For example, consider a trivial (hypothetical) overload, that would be equivalent to the default implementation of the operator:

     class Foo


       public static operator=(out Foo foo1, Foo foo2)


         foo1 = foo2;



     class Bar


       public explicit operator Foo(Bar bar)


         return new Foo();



     Bar bar = new Bar();

     Foo foo;

     foo = bar;

    This is equivalent to:

     operator=(out foo, bar);

    Which is equivalent to:

     operator=(out foo, explicit operator Foo(bar));

    In other words, by the time the assignment operator = gets the operands, they’ve already been resolved/converted as needed.

    Of course, the assignment operator isn’t overloadable, so the above is purely hypothetical.  But IMHO it’s certainly one valid way to interpret the assignment operator, and doing so makes clear that the type of the value on the right-hand-side of the operator must already be the correct type for the destination (the left-hand-side).

    I understand the point you’re trying to make and I think it is plausible, but ultimately not productive to consider “the value of the right hand side” as being the value after the conversion to the type of the left hand side.

    We would like to write a specification that states what the value of any expression is. (For those expressions that have a value. The expression “Console.WriteLine(123);” has no value.) It is awkward in the extreme to have to work out what the value of an expression is if its type depends on stuff outside of the expression. (We are in this situation with lambda expressions, which have neither values nor types, and are thereby tricky to specify.)

    In particular, it is extremely awkward to write the “conversion” section of the specification. For example, we say that an implicit boxing conversion exists between a expression whose value is of a value type and the type object. You say “object x = 2 + 2;” Analyze it.

    My way: the value of 2 + 2 is the integer 4, a value type, and therefore this is a boxing conversion to object.

    Your way: the type of the value of the right hand side of an assignment expression is of the type of the left-hand side. Therefore the value of the right hand side is of type object, a reference type, and therefore this is not a boxing conversion.

    That’s crazy. We need to be able to talk about the type of an expression *before* any conversion happens because that’s how we’re going to work out which conversion, if any, is valid. If we go with your way, and say that the type of the right hand side of an assignment is always of the type of the left hand side, then how do we word the specification clearly to figure out what conversion it is?

    Also, consider overload resolution. When you say void M(double x) {} and have a call M(123), essentially what you are doing is assigning 123 to formal parameter variable x. Now suppose we have both M(double x) and M(short x). Are you telling me that the type of 123 is both double and short in M(123) because it could be assigned to double or it could be assigned to short? Again, that’s crazy. We need expressions that have a value and type to have a specific value and type independent of their context, because *the correct context is what we’re trying to work out*.

    — Eric


  10. Jayson says:

    I have always been so curious of this type of assignment and have sparingly used it because I didn’t want to use it without understanding the assignment.

    Thanks for the clarification, Eric!

  11. Grico says:

    I think I understand how the “value” side of a chained assignment works. What I’m, still trying to decypher is how the types are passed and if it abides the same rules.

    The example Eric uses:

    const int x = 10;
    short y;
    object z;
    z = y = x;

    I dont quite see how this example plays according to the “value assigned to the left hand side” rule.

    y=x; x is clearly an int, therefore y=x should evaluate to what is assigned to y which is an  int.

    Then z should be assigned an int too but it somehow ends up with a short. I’m either missing something basic or types dont follow the same rule values do.

    My guess is that z=y=x is under the hood converted to z=y=(short)x, so the conversion is before the assignment.

    The operation of the assignment operator is (1) evaluate  the left hand side to determine the location of the variable (or property, or whatever). (2) evaluate the right hand side. (3) convert the result of step 2 to the type of the left hand side via the appropriate conversion, (4) assign the result of step 3 to the result of step 1.  The value of the right hand side is the result of step 2. The value assigned to the left hand side is the result of step 3. Those can be very different. Pete seems to believe that we should consider the value of the right hand side to be the value computed by step 3, but I disagree.  — Eric 

  12. Grico says:

    z=y=x is converted to z=(object)(y=(short)x) is what i meant to say. So basically z=(object)(short)x. Is this true? Or am i misunderstanding everything?

    Correct. — Eric

  13. pete.d says:

    I note that I’m not the compiler implementor, nor the language designer, and obviously not the one with expert knowledge in this field.  That said, I can still answer questions asked of me.  🙂

    Q: “If we go with your way, and say that the type of the right hand side of an assignment is always of the type of the left hand side, then how do we word the specification clearly to figure out what conversion it is?”

    A: I would look to some kind of recursive definition of the conversion, such that the conversion is defined in terms of simpler conversions.

    Q: “Now suppose we have both M(double x) and M(short x). Are you telling me that the type of 123 is both double and short in M(123) because it could be assigned to double or it could be assigned to short?”

    A: No, I’m not saying that.  But your question stems from a chosen approach to overload resolution, presupposing that choice.  It seems to me that overload resolution could be defined to take into account the question of conversion, such that overload resolution includes an attempt to convert the expression to each of the available destinations for the assignment, and the “best” overload is in fact a consequence of the “best” conversion.

    That said, it seems to me that your reply is really saying that this isn’t just about the _compiler_ implementation, but rather about the language specification.  Inasmuch as in the specification you do have to choose a specific way to describe these conversions, overload resolutions, etc. I am perfectly satisfied with _that_ justification for this particular way to look at the question.

    In other words, given a specific choice with respect to how the language in the specification is constructed, I see how my argument doesn’t apply.

    But, that doesn’t mean that it’s a technically impossible argument (the specification could have been worded differently), and as pedantic as it might be to do so, I do still disagree with the characterization of the consequences of the wording of the specification being “clear”, at least in absence of a specific reference to that specification (i.e. until you mention the specification, you can’t say a particular interpretation of the specification is “clear” 🙂 ).

    Anyway, thanks for setting me straight.

    Like I said, your argument is plausible. But it turns out to be less vexing to describe the operation of the assignment as having two clearly distinct steps in the middle of its operation: computing the value of the right hand side, and computing the value that is assigned to the left-hand side. And of course, that is what really happens in the runtime; we compute the right hand side, then we run the appropriate conversion code, and then we do the assignment. — Eric

  14. Grico,

    You are confusing "the value of the RHS" and what happens as part of an assignment. When talking about RHS values, it refers to the value BEFORE any effects of the operation. Looking at it another (semantic) way. "x" is the RHS alll by  itself. At no time does "x" have any other value or type (i.e. it is NOT mutated by the operation that is being performed.

  15. tim says:

    The number one rule of programming is write clearly.  If the original code had been written clearly in the first place there would be no need for this discussion.

  16. Pavel Minaev [MSFT] says:

    It’s not really surprising, in that it is fully consistent with C, C++ and Java, while sharing the same syntax. That makes sense to me.

    Those three all define the result of the assignment operator as "the value of the variable after assignment", but of course they also don’t have properties. So far as I can see, when properties are not involved, there’s no difference between "new value of variable", and "assigned value converted to type of variable", so where they intersect with C#, semantics are consistent; and otherwise the rule is a logical extension, preserving the spirit while taking into account the existence of write-only properties.

  17. Fusion says:

    Consider slightly changed piece of code:

    class C


     private string x;

     public string X {

       get { return x ?? ""; }

       set { x = value + "a"; } }

     static void Main()


       C c = new C();

       object z;

       z = c.X = "b";





    It writes "b" and "ba".

    Shouldn’t the statement be rather " the result of the simple assignment operator is the value that was >used to be< assigned to the left-hand side" ?

    Can you think about another wierd example? 🙂

  18. Fusion,

    Whe dealing with properties, "the value that was assigned" has to be treated as "the parameter that was passed to the setter", and NOT as "the internal value of any backing field or calculation". Actions that take place within the setter (and getter) are not (and IMPO should not) be considered as they are internal implementation details.

  19. Chris B says:

    "I’m of the opinion that side effects such as assignments are best represented by putting each in a statement of its own, rather than as something embedded in a larger expression."

    Agreed. I need to be able to focus on more important problems in my code than what the value of "i += ++i + i++;" will be.  I’d rather communicate my intentions and perform one operation per line of code and let the compiler figure out how to optimize it.  It’ll probably do a better job than I could anyway.

    Unless there is a case where the compiler would generate different or more efficient code because you wrote something like:

    int a = b = c = 1;

    as opposed to:

    int a = 1;

    int b = 1;

    int c = 1;

    I don’t see much reason to perform multiple operations (excluding basic get/set operations) in a single line.  I find it just muddles things up and makes it more difficult to figure out the order of execution and why it needs to be executed that way.  I think both should always be made as obvious as possible, but the "why" is allowed some more wiggle room.

  20. in C and Perl, I’ve frequently used the pattern of

    if (x = openSomethingOrOther()) {

     do something with x



    Works in JavaScript too but I don’t remember whether or not I’ve used it.

    In Java and C# that becomes less useful since non-bool expressions can’t be used as the condition for if statements.

    I’ve also used something like:

    while ((str = stream.ReadLine()) != null) {



    and similar tricks using a character variable to read from a stream up to a terminating character. I think it’s almost always ugly code, and as I’ve moved exclusively to C# and the language and the BCL have gotten better at providing cleaner ways to do these things at a nicer level of abstraction (foreach (var line in File.ReadAllLines(…)) for example) I’ve used it less and less.

    That help?

  21. Jason says:

    real world using assignments as expressions / chained assignments      

     protected virtual void OnGetWindowSizes(ref short minimumWidth, ref short minimumHeight, ref short maximumWidth, ref short maximumHeight, ref short preferredWidth, ref short preferredHeight)


               if (WidthAt96DPI != 0 && HeightAt96DPI != 0)


                   using (System.Drawing.Graphics g = CreateGraphics())


                       short scaledWidth = (short)(WidthAt96DPI * g.DpiX / 96);

                       short scaledHeight = (short)(HeightAt96DPI * g.DpiY / 96);

                       if (AllowUserToResizeTool)


                           minimumWidth = preferredWidth = scaledWidth;

                           minimumHeight = preferredHeight = scaledHeight;




                           minimumWidth = maximumWidth = preferredWidth = scaledWidth;

                           minimumHeight = maximumHeight = preferredHeight = scaledHeight;





    refs due to some C++ interop.

  22. David Nelson says:

    I don’t make a habit of it in the general case, but I can think of one pattern I use that takes advantage of this feature. Consider the following pseudo-code:


    Get value

    IF value satisfies some predicate THEN

      Use value in additional processing



    The easiest way (IMHO) to express this is with code similar to the following:

    string input;

    while(input = GetInputFromUser() != "quit")




    You could use a boolean return value and an out variable instead to avoid evaluating the assignment as an expression, but that is considerably less usable and readable in my opinion.

    Also, it seems to me that following usage of the "using" keyword would fall into this category:

    SqlConnection conn;

    using(conn = new SqlConnection(…))



    Although I can’t be sure the language spec doesn’t special case this scenario, as it would have to if the declaration of "conn" were inside the using expression.

  23. Pavel Minaev [MSFT] says:

    Pretty much the only place where I ever use this pattern is when reading a file line-by-line:

      string str;

      while ((str = reader.ReadLine()) != null) { … }

    The reason is that alternatives are either repeating the call to ReadLine twice, or using while(true), with the assignment and if/break inside. I don’t like either.

  24. pete.d says:

    I generally agree with the sentiment to keep side-effects separate.  But, like other responders, there are a handful of places where I commonly do in fact use the assignment expression value.  Oddly enough, they are mostly similar to Pavel’s example, fit the pattern David Nelson describes, and fall into the broader category of i/o operations.

    StreamReader.ReadLine() returns null reaching the end of input, Stream.Read() returns 0, likewise Socket.Receive(), in a console application, I might loop until Console.ReadLine() returns "", etc.  Making these checks as the condition at the top of a "while" loop results in code that is IMHO more readable than the alternatives.

    Much less commonly, I do find myself doing a similar kind of thing in "if" statements.  In some respects, those examples can probably be thought of degenerate, single-iteration versions of the "while" loop scenario, though in the "if" statement examples, I would say that the i/o scenario isn’t quite so highly correlated.

    In short, it’s not a construct I use broadly.  But if C# didn’t allow assignments to be treated as expressions, I would definitely miss that feature.

  25. Pavel Minaev [MSFT] says:

    Sather has an interesting form of loops which lets you write this in a readable way, by allowing "while" (or other iterator – it’s actually extensible, and "while" is not a keyword) itself to appear in the middle of the body:


         s: STR := #IN.get_line

      while!(s /= void)



    It’s not really all that different from if/break at that point, but still more clear in intent, IMO.

  26. Chris B says:

    In the case of IO operations and loops, I think I’d rather see processing look more like this:



       string s = stream.ReadLine();


    Using the magic return value of null to indicate EOF is unclear because it requires consumers to have knowledge of that return value.  I think this would also eliminate the problems Pavel mentions with calling Read() twice and using a while(true)/break construct.

    Of course, there is not currently a Stream.EndOfStream property, nor do I have any idea what would be required to make that happen, but a guy can dream, right?

  27. pete.d says:

    "Using the magic return value of null to indicate EOF is unclear because it requires consumers to have knowledge of that return value."

    For better or worse, we’re stuck with that.  Many APIs have no way to even know whether they’ve reached the end-of-input without a read operation.  For example, network sockets.  Your code may have read all available data without reaching the end-of-input and be sitting there with another blocking read.  And that next blocking read could be the one where end-of-input is reported, much later (i.e. at the time all the data was consumed, it wasn’t yet known that the end-of-input had been reached).

    Sure, you could refactor the code so that it could (for example) handle a zero-byte input properly before going back and checking the special "end-of-stream" property.  But that’s a lot of overhead for little practical benefit.

    I suppose if we could design a complete computing environment from the ground up, it could be designed such that input streams always have a known end-of-input that can be identified without trying to read more input.  But a) it’s not clear that such an environment would in fact be a practical improvement on the current situation, and b) obviously it’s simply not practical to do that anyway.  New computing systems have to be able to operate with existing ones.

    And even if we did somehow overcome all those practical obstacles, we’d still be stuck with the fact that not ALL uses of assignments as expressions with value fall into that category.  Even if you could get rid of the end-of-input-as-part-of-a-read scenario, we’d still have places where it would be useful to evaluate the outcome of an assignment operation.

  28. Michael Liu says:

    When I’m forced to switch on the type of a value, I use the following pattern:

    private static IPropertyWriter GetPropertyWriter(Object value)


       String str;

       IEnumerable enumerable;

       Pair pair;

       Triplet triplet;

       if ((str = value as String) != null)


           return new StringWriter(str);


       else if ((enumerable = value as IEnumerable) != null)


           return new EnumerableWriter(enumerable);


       else if ((pair = value as Pair) != null)


           return new PairWriter(pair);


       else if ((triplet = value as Triplet) != null)


           return new TripletWriter(triplet);




           return null;



  29. pete.d says:

    "When I’m forced to switch on the type of a value, I use the following pattern:"

    Taking as granted that you might indeed be forced into that kind of logic (I would say that generally one should try to avoid having to have conditions that depend on the specific type), it seems to me that a more maintainable approach would be to set up a data-driven framework to do that kind of work.  For example:

           static IPropertyWriter GetPropertyWriter(Object value)


               return GetMappedObject(value, _rgmm);


           static MethodMap<IPropertyWriter>[] _rgmm = new MethodMap<IPropertyWriter>[]


               new MethodMap<IPropertyWriter>(typeof(string), (obj) => new StringWriter((String)obj)),

               new MethodMap<IPropertyWriter>(typeof(IEnumerable), (obj) => new EnumerableWriter((IEnumerable)obj)),

               new MethodMap<IPropertyWriter>(typeof(Pair), (obj) => new PairWriter((Pair)obj)),

               new MethodMap<IPropertyWriter>(typeof(Triplet), (obj) => new TripletWriter((Triplet)obj))


           struct MethodMap<T>


               public readonly Type Type;

               public readonly Func<object, T> Mapper;

               public MethodMap(Type type, Func<object, T> mapper)


                   Type = type;

                   Mapper = mapper;



           static T GetMappedObject<T>(object value, MethodMap<T>[] rgmm)


               foreach (MethodMap<T> mm in rgmm)


                   if (mm.Type.IsInstanceOfType(value))


                       return mm.Mapper(value);



               return default(T);


    Once you’ve got the basic boilerplate above in place, it’s a lot simpler to add that kind of mapping than to have to keep writing a bunch of if/else chains.  Just create/add a new element to an array that describes the relationship.

  30. Gabe says:

    Here’s some code that chains assignments to set properties while remembering their values for later:

    class GraphicalThing {

           Path line;

           GeometryGroup geom;

           public GraphicalThing() {

               Children.Add(line = new Path() { Data = geom = new GeometryGroup { FillRule = FillRule.Nonzero } });

    I think that’s the only time I use chained assignments in C#.

  31. I use assignments as expressions often, for lazy loading of readonly properties:

    private MyObject myObject = null;

    public MyObject MyObject {

       return myObject ?? (myObject = Repository.GetMyObject());


  32. Michael Liu says:

    @pete.d: Indeed, I’ve used a Dictionary<Type, Func<Object, …>> in other scenarios. But a map seems like overkill when the number of types is very small.

  33. pete.d says:

    Re: map vs if

    Well, you couldn’t use a dictionary in your example.  Your code prioritizes the types, and includes a type that can’t actually be used in a search (IEnumerable).  That’s why my example uses an array instead (initialized in priority order).

    But note that in cases where a dictionary would apply, you could also write that as a switch (for types, you’d have to switch on .GetType().FullName).  And if you do that, the compiler’s just going to convert that to a dictionary anyway, if you have more than six choices (for C# 3.0 anyway).

    That said, if you really love the if/else if pattern, it works fine and I certainly wouldn’t argue that there’s anything wrong with it per se.  And even though these days, in those kinds of situations I do in fact write the assignment as a separate statement, I’ve in the past been known to include it in the if statement itself.  Seems like a fine use of that construction, if that’s what you prefer.

  34. Re: "do you use assignments as expressions?"

    As others have mentioned, I use using statements with the result of an initialisation as the paramter (which I suspect is something different to an assignment, strictly speaking.)

    I would use the while ((s = Read()) != null) pattern. but I don’t really like the look of it with all those brackets and = operators where == operators normally go. So I use the while (true) { s = Read(); if (s == null) break; /*…*/} pattern instead.

    I wouldn’t mind some syntactic sugar for that while loop to look nicer. Does C#3 or 4 provide anything to help out there? (Something like an anonymous function that returns something foreach can use.)

  35. As other commentors have done, I’ve written the following code for Streams:

       static byte[] BufferedReadAll(Stream stream)


           byte[] buffer = new byte[16*1024];

           using (MemoryStream ms = new MemoryStream())


               int bytesRead;

               while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) != 0)


                   ms.Write(buffer, 0, bytesRead);


               return ms.ToArray();



    and for ASP.NET MVC, I’ve seen this for alternate rows:

       public static void AlternateRows<T>(this IEnumerable<T> dataSource, Action<T, bool> func)


           if (dataSource == null)


           bool rowState = true;

           foreach (var item in dataSource)

               func(item, (rowState = !rowState));


  36. Michael Liu says:

    Another possible use of the assignment operator:

    A a = …;

    B b;

    C c;

    D d;

    if ((b = a.GetB()) != null &&

       (c = b.GetC()) != null &&

       (d = c.GetD()) != null &&



       // Do something if a.GetB().GetC().GetD().IsE is true…




       // Do something else…


  37. Thomas G Mayfield says:

    I’ve (only recently) started using them for simple property initializers.  I only use it where the initialization of the field would be a simple, single line, as otherwise this could cause some serious maintenance headaches.  My first exposure to the style was from ReSharper.

    What used to be:

        private string _foo;

        public string Foo




                if (_foo == null)


                    _foo = ComplexFooCreator.GetMeSomeFoo();


                return _foo;



    is now:

        private string _foo;

        public string Foo


            get { return _foo ?? (_foo = ComplexFooCreator.GetMeSomeFoo());}


    (Not knowing if your blog does tabs or spaces, I’ve done both. And boy does that hurt my sensibilities.)

  38. RobS says:

    The use of such constructs is simply out of laziness…and most programmers seem to be inherently lazy.  Why be clear in your code when you can be quick, especially when your boss wants you to get everything out yesterday?

  39. Gabe says:

    RobS: I found the following in my code this morning:

       min = max = ComputeInitialValue();

    What would be clearer? This:

       max = ComputeInitialValue();

       min = max;

    Or is that too lazy? Maybe you think it should be this:

       readonly var initialValue = ComputeInitialValue();

       min = initialValue;

       max = initialValue;

    BTW, only bad programmers aren’t inherently lazy. But laziness isn’t the topic here. When I see something like "while ((str = reader.ReadLine()) != null) {…}", I don’t think it’s the programmer being lazy; I think that it’s just more clear than "while (true) { str = reader.ReadLine(); if (str == null) { break; } …}". Making the guard condition on the loop explicit makes the loop easier to understand. I can clearly see that it’s a loop to read all the lines in a stream rather than a loop that just happens to read a line from a stream at the beginning of every iteration.

  40. Ben Voigt [C++ MVP] says:

    Common use of assignment in expression (particular case is C++, but has C# analogues):

    if (FAILED(hr = CoDoSomething())) {




    But, is the result of the assignment expression actually a value, or actually a reference to the left-hand side variable?  In C++, it is the latter (barring really unusual override of operator=), so you can, for example, initialize a pointer with its address.  I don’t use pointers in C# that much, maybe the syntax prevents any case where you would actually be able to discern the difference between value and reference to assigned variable.

  41. Grahame says:

    How about a wording like this: "the result of the simple assignment operator is the resultant value that was assigned to the left-hand side."

    This would handle the case where a property getter returns a different value to what was passed to the setter.

  42. Kenneth Xu says:

    >> The result of the simple assignment operator is not the value of the right hand side:

    >> const int x = 10;

    >> short y;

    >> object z;

    >> z = y = x;

    >> System.Console.WriteLine(z.GetType().ToString());

    You have missed one important point, if you read the language specification. The type of expression

    y = x

    is short, not int. Because here compiler put in an implicit cast. The effective statement is

    z = y = (short)x;

    So it is always correct that "results in the value of the right-hand side”. Never half!


  43. JoshF says:


    Here’s one situation were I routinely use assignments as expressions (one of the only places that I feel it’s less messy than the alternatives):

    Dictionary<string, HashSet<Member>> _blacklistedMembersByPlace = new Dictionary<string, HashSet<Member>>();

    public bool BlacklistMember(string place, Member member)


    HashSet<Member> members;

    if (!_blacklistedMembersByPlace.TryGetValue(place, out members))

    _blacklistedMembersByPlace.Add(place, members = new HashSet<Member>());

    return members.Add(members);


  44. Timwi says:

    The only place I’ve ever used assignments as expressions in C# (besides chaining) is when matching a single input string against several possible regular expressions. My code will then generally look something like this:

    Match m;

    if ((m = Regex.Match(…)).Success) {

     // Process, using m.Groups

    } else if ((m = Regex.Match(…)).Success) {

     // Process, using m.Groups


    The important thing to note here is that the code inside the if needs access to m.Groups, otherwise I could just use Regex.IsMatch().

    Of course I realise that I could write it like this:

    Match m = Regex.Match(…);

    if (m.Success) {

     // Process, using m.Groups

    } else {

     m = Regex.Match(…);

     if (m.Success) {

       // Process, using m.Groups



    but once you have three or four regular expressions, the first one starts looking quite a lot cleaner.

  45. Mark says:

    This is Java code, just for note, but the simplest use of assignment chaining is when new objects are required.


               treescrollpane = new javax.swing.JScrollPane(

                   datatree = new javax.swing.JTree(

                       treemodel = new javax.swing.tree.DefaultTreeModel(







    Here you can see that I chained quite a few assignments in the one expression. Now, you can argue that the need to do this in the first place is an example of bad design – I certainly won't argue that Java isn't badly designed – but the example is the same. Assignment chaining works well when you need both a variable AND a value.

  46. Mike says:

    U asked about real usage? is this is still meanfull here it is:

    Most common usage is clearing some data in class or form, something like this:

    a) this.a = this.b = this.c = 0;

    b) ed1.Text = ed2.Text = ed3.Text = string.Empty;

    so, most common usage is data clear, when recreation of actual object is very slow task (complex form, f.e.).

    Happy New Year!

Comments are closed.

Skip to main content