vehomzzz
vehomzzz

Reputation: 44598

Question about Immutability and object initialization from C# in depth 2nd. ed( MEAP)

So I started reading Jon Skeet's 2nd edition of C# in depth and kind of confused about the following code in terms what it does and what is wrong with it (ch 13, section: Immutability and object initialization)

Message message = new Message(
"[email protected]",
"[email protected]",
"I hope you like the second edition")
{
       Subject = "A quick message"  // <=  {Subject = "A quick message"   }; what is it?
};

Elaboration on this topic, would help tremendously!

Would someone explain that?

Upvotes: 0

Views: 225

Answers (3)

Jon Skeet
Jon Skeet

Reputation: 1502016

This code:

Message message = new Message(
"[email protected]",
"[email protected]",
"I hope you like the second edition")
{
       Subject = "A quick message"
};

is equivalent to this:

Message tmp = new Message("[email protected]", 
    "[email protected]",
    "I hope you like the second edition");
tmp.Subject = "A quick message";
Message message = tmp;

That's just object initializer syntax: see chapter 8 for more details.

The problems with this are:

  • It's not clear what all the string arguments mean - what's "from", what's "to", what's the body etc
  • It requires the type to be mutable (unfortunate for all kinds of reasons)
  • If you want to also specify the subject in the constructor, you end up with a bunch of different overloads
  • If you have cross-validation between (say) subject and body, you need to be careful about when you do it

With optional parameters and named arguments, all of this is solved:

// The argument names may be wrong here; I don't have the book with me.
// Intellisense will prompt you though :)
Message message = new Message(
    from: "[email protected]",
    to: "[email protected]",
    body: "I hope you like the second edition",
    subject: "A quick message);

It's clear what means what, it's all in a constructor call so the type can be immutable, you can have a single constructor with optional parameters (e.g. here we could have a byte[] attachment = null parameter specified in the constructor), and you can do all the validation in one place. Lovely.

Upvotes: 5

Gishu
Gishu

Reputation: 136633

Let's look at it this way

 Message message = new Message(
    "[email protected]",
    "[email protected]",
    "I hope you like the second edition")

^^^ This part of the expression invokes the ctor of Message which takes 3 string parameters

 {
           Subject = "A quick message"  // <=  {Subject = "A quick message"   }; what is it?
    };

^^^ The next part then sets the Subject property on the new instance to the given value. This block is called the object initializer. You can set any property at most once in this block.

There are multiple way to initialize an object.. the following could all have the same effect. (Assumption: message class has public properties called From, To and Subject)

Message m = new Message() {From="F", To="T", Subject="Whatever"}; // default ctor followed by property setters
Message m = new Message {From="F", To="T", Subject="Whatever"}; // allowed to omit paranthesis for default ctor
Message m = new Message(sFrom, sTo) {Subject="Whatever"}; // parameterized ctor followed by property setter

Object initializers are essential when dealing with anonymous types / in LINQ. The following line creates a new instance of an anon type with From, To and Subject properties

var newMessage = new {From="F", To="T", Subject="Whatever"};

For more on this, refer to this MSDN page - Object and Collection Initializers

However object initializers require properties to be public and consequently the underlying types to be mutable. It is generally preferred to have "immutable" (once created, the value of the object doesn't change) data structures to prevent side-effects or accidental modification. Maybe that's the point Jon was trying to make... I dont have the 2nd ed.

Upvotes: 2

Noon Silk
Noon Silk

Reputation: 55112

Well, the "Message" class is clearly mutable, as you are setting various properties; in the constructor and in the initialisation clause.

It's also confusing, I imagine, because he's setting the 'subject' field twice. Which one will be used?

Upvotes: 2

Related Questions