6

For the hardcore C# coders here, this might seem like a completely stupid question - however, I just came across a snippet of sample code in the AWS SDK forum and was completely sideswiped by it:

   RunInstancesRequest runInstance = new RunInstancesRequest()
    .WithMinCount(1)
    .WithMaxCount(1)
    .WithImageId(GetXMLElement("ami"))
    .WithInstanceType("t1.micro");

This is very reminiscent of the old VB6 With ... End With syntax, which I have long lamented the absence of in C# - I've compiled it in my VS2008 project and it works a treat, saving numerous separate lines referencing these attributes individually.

I'm sure I've read articles in the past explaining why the VB6-style With-block wasn't in C#, so my question is: has this syntax always existed in the language, or is it a recent .NET change that has enabled it? Can we coat all object instantiations followed by attribute changes in the same sugar?

Eight-Bit Guru
  • 9,756
  • 2
  • 48
  • 62
  • 2
    Well sure, you can implement all those methods if you want. But why not just use object initializer syntax? – Kirk Woll Oct 15 '10 at 14:14
  • 1
    Excellent answers here, but I can only accept one - so for right now it's the one that specifically refers to *Fluent Interfacing*, because the example in the article makes it very clear what's going on. I feel slightly embarrassed that I didn't make the intuitive link myself, spotting that the line as a whole is of the form 'A.B.C.D;', but I've never seen the technique before. Another string to the bow! :) – Eight-Bit Guru Oct 15 '10 at 14:34

10 Answers10

26

Isn't this better anyway?

RunInstancesRequest runInstance = new RunInstancesRequest 
{
    MinCount = 1, 
    MaxCount = 1, 
    ImageId = GetXMLEleemnt("ami"), 
    InstanceType = "t1.micro"
};
Kirk Woll
  • 76,112
  • 22
  • 180
  • 195
  • I agree, for setting properties/constructors, this is a better syntax. But in scenarios where you are working with an existing item, and will often be modifying several properties, or calling several methods in a chain, fluent interfaces shine. It's one of the many reasons jQuery is so nice to work with. – CaffGeek Oct 15 '10 at 14:41
  • 1
    And you can't use it on an immutable object. Personally I think this syntax should only be used if the original object isn't modified(like in Linq). – CodesInChaos Oct 15 '10 at 15:14
  • 1
    It's one additional object per step. And I'm pretty sure Linq creates one instance which implements IEnumerable per step on query creation. And one IEnumerator per step on query evaluation. I don't think the spurious objects matter much since they'll probably get collected in the generation 0 GC. – CodesInChaos Oct 15 '10 at 15:23
16

They implemented all those methods, each of which will also be returning the RunInstancesRequest object (aka, this). It's called a Fluent Interface

CaffGeek
  • 21,856
  • 17
  • 100
  • 184
4

It is not syntactic sugar. Those methods just set a property and return the this object.

Klaus Byskov Pedersen
  • 117,245
  • 29
  • 183
  • 222
4
RunInstancesRequest runInstance = new RunInstancesRequest()
.WithMinCount(1)
.WithMaxCount(1)
.WithImageId(GetXMLElement("ami"))
.WithInstanceType("t1.micro");

==

RunInstancesRequest runInstance = new RunInstancesRequest().WithMinCount(1).WithMaxCount(1).WithImageId(GetXMLElement("ami")).WithInstanceType("t1.micro");

I don't know if that's considered syntactic sugar, or just pure formatting.

ManAmongHippos
  • 511
  • 1
  • 5
  • 9
3

I think this technique is different than the With... syntax in VB. I think this is an example of chaining. Each method returns an instance of itself so you can chain the method calls.

See Method-Chaining in C#

Community
  • 1
  • 1
Michael Levy
  • 13,097
  • 15
  • 66
  • 100
1

The reason this syntax works for RunInstancesRequest is that each of the method calls that you are making return the original instance. The same concept can be applied to StringBuilder for the same reason, but not all classes have methods implemented in this way.

Mark Avenius
  • 13,679
  • 6
  • 42
  • 50
1

I would prefer having a constructor that takes all of those property values as arguments and sets them within the class.

Bernard
  • 7,908
  • 2
  • 36
  • 33
  • +1. I dislike anything that lets partially-constructed classes live. I just about put up with it for LINQ2SQL or other ORMs as an artefact of OO-ORM impedance, but there's no justification most of the time. Doesn't mean it can't be used along-side proper constructors and class invariants, but I can see how this would encourage breaking away from that. – Jon Hanna Oct 15 '10 at 17:02
1

It's always existed in C# and indeed in any C-style oo language (eh, most popular C-style language except C itself!)

It's unfair to compare it the the VB6 With...End With syntax, as it's much clearer what is going on in this case (about the only good thing I have to say about VB6's With...End With is at least it isn't as bad as Javascripts since it requires prior dots).

It is as people have said, a combination of the "fluent interface" and the fact that the . operator allows for whitespace before and after it, so we can put each item on newlines.

StringBuilder is the most commonly seen case in C#, as in:

new StringBuilder("This")
  .Append(' ')
  .Append("will")
  .Append(' ')
  .Append("work")
  .Append('.');

A related, but not entirely the same, pattern is where you chain the methods of an immutable object that returns a different object of the same type as in:

DateTime yearAndADay = DateTime.UtcNow.AddYears(1).AddDays(1);

Yet another is returning modified IEnumerable<T> and IQueryable<T> objects from the LINQ related methods.

These though differ in returning different objects, rather than modifying a mutable object and returning that same object.

One of the main reasons that it is more common in C++ and Java than in C# is that C# has properties. This makes the most idiomatic means of assigning different properties a call to the related setter that is syntactically the same as setting a field. It does however block much of the most common use of the fluent interface idiom.

Personally, since the fluent interface idiom is not guaranteed (there's nothing to say MyClass.setProp(32) should return this or indeed, that it shouldn't return 32 which would also be useful in some cases), and since it is not as idiomatic in C#, I prefer to avoid it apart from with StringBuilder, which is such a well-know example that it almost exists as a separate StringBuilder idiom within C#

Jon Hanna
  • 110,372
  • 10
  • 146
  • 251
0

This syntax has always existed

Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
-2

Please refer to Extension Methods (C# Programming Guide)

Salizar Marxx
  • 917
  • 6
  • 11