6

Can you please tell me what kind of construct in C# is this.

Code Golf: Numeric equivalent of an Excel column name

C.WriteLine(C.ReadLine() 
            .Reverse() 
            .Select((c, i) => (c - 64) * System.Math.Pow(26, i)) 
            .Sum());

Though I am new to C# (only two months exp so far), but since the time I have joined a C# team, I have never seen this kind of chaining. It really attracted me and I want to learn more about it.

Please give some insight about this.

Community
  • 1
  • 1
Thinking
  • 201
  • 2
  • 11

4 Answers4

9

Method chaining like this is often called a fluent interface.

You can make your own fluent interface by implementing functions that return the object they were called on.

For a trivial example:

class Foo 
{
    private int bar;

    public Foo AddBar(int b) 
    {
        bar += b;
        return this;
    }
}

Which can be used like:

Foo f = new Foo().AddBar(1).AddBar(2);

You could also implement a fluent interface using extension methods.

For example:

class Foo 
{
    public int Bar { get; set; }
}

static class FooExtensions 
{
    public static Foo AddBar(this Foo foo, int b)
    {
        foo.Bar += b;
        return foo;
    }
}

etc.

Here is a more complex example. Finally, Autofac and CuttingEdge.Conditons are two examples of open-source libraries that have very nice fluent interfaces.

Matthew King
  • 5,114
  • 4
  • 36
  • 50
  • you probably mean `return this;`, not `bar`. Either way, this isn't exactly the case here, but the concept in similar enough. – Kobi Apr 14 '10 at 04:54
  • You probably want to return a new Foo with the result, to avoid side-effects. – Dave Van den Eynde Apr 14 '10 at 05:12
  • 2
    Dave, you are right that returning a new Foo will avoid side-effects. However, in this instance, having side-effects is a pretty integral part of the fluent interface. The side effects are intended. – Matthew King Apr 14 '10 at 06:40
  • "CuttingEdge.Conditons ... nice fluent interface". Thanks for the compliment :-) – Steven Apr 29 '10 at 17:34
2

There's nothing special about most of the expression, but the select method makes use of lambda expressions, a key component of Language Integrated Query - LINQ, for short.

.NET Language-Integrated Query defines a set of general purpose standard query operators that allow traversal, filter, and projection operations to be expressed in a direct yet declarative way in any .NET-based programming language.

LINQ, and the lambda expressions they use, are a way to write complicated query and manipulation expressions succinctly and readably. It was added to the .NET Framework in 3.5. Here's some more information from MSDN.

Michael Petrotta
  • 59,888
  • 27
  • 145
  • 179
2

It's little more than a chain of function calls with some indentation, where C calls ReadLine(), whose result is used for Reverse, whose result is used for Select, etc. The functions themselves are part of LINQ, the ones that get used after translating the syntactic sugar. Here's a list of LINQ query functions, along with samples on their use, and here's a tutorial for LINQ.

(In case you're interested: Reverse() returns an IEnumerable that goes from back to front of the given IEnumerable, Select() returns an IEnumerable listing all elements, after applying the given lambda expression, and Sum() simply returns the sum of all the elements of the given IEnumerable.)

Mauricio
  • 1,683
  • 12
  • 18
1

The chaining pattern can be called a Fluent Interface. It occurs when an interface's function (or extension method) returns the same interface. In this case, it is IEnumerable.

You also have some LINQ thrown in there with the Select and Sum functions

foson
  • 10,037
  • 2
  • 35
  • 53
  • It doesn't have to be the same interface. It doesn't even have to be an actual interface. – Mauricio Scheffer Apr 14 '10 at 04:46
  • Strictly speaking, `IEnumerable` and `IEnumerable` are not the same interface. A fluent interface is usually when the functions end with `return this;`, so you can do `Foo.Open().Add(2).Close(); ` instead of `Foo.Open(); Foo.Add(2); Foo.Close()`. LINQ returns a new enumerable (sort of), so this is regular chaining. – Kobi Apr 14 '10 at 04:50
  • I disagree, Kobi. I think you should never return 'this', to avoid side-effects. – Dave Van den Eynde Apr 14 '10 at 05:14
  • 2
    Unless you want side effects. This depends on what you're doing, in many cases you don't want to create a new object (consider `StringBuiler`, for example). If you're trying to avoid side effects you *have* to return a new instance, but I don't think this is the same as a fluent interface (at least it wasn't when I learned it...) – Kobi Apr 14 '10 at 05:32