0

I discovered yesterday that I can simulate a fluent interface if I return the class instance from each method like this...

public class IsThisFluent
{
    public IsThisFluent Stuff()
    {
        //...
        return this;
    }

    public IsThisFluent OtherStuff()
    {
        // ...
        return this;
    }
}

Is this all there is to it?

I admit, I'm a bear of very little brain and I want to carry on this this but I thought it might be best to check with a grown up.

Am I missing something?

Is there a 'gotcha' that I haven't spotted with this pattern?

Stuart Hemming
  • 1,553
  • 2
  • 21
  • 44
  • that's the way i do it all the time... have a look at this: http://www.codeproject.com/Articles/640997/Fluent-interfaces-and-Method-Chaining-in-Csharp – stefankmitph Apr 17 '15 at 08:57
  • 3
    It's fairly common to do this when you are working with immutable classes. There's a good video of Jon Skeet somewhere writing a Tetris console application with this pattern. Edit: here it is... https://vimeo.com/68331762 – DavidG Apr 17 '15 at 08:58
  • It kind of depends on how you intend to use it, Does stuff really need to return anything or do anything with the object afterwards? I'm not sure how much of a performance hit this would make to return objects just for the sake of it – Sayse Apr 17 '15 at 08:59
  • Thx for that. The article doesn't highlight any potential problems; can I assume, then, that there aren't any. – Stuart Hemming Apr 17 '15 at 09:02

3 Answers3

4

That's pretty much it.

Here's a really good article on it: http://rrpblog.azurewebsites.net/?p=33

EDIT
The original site seems to have died, so here's WayBackMachine to the rescue

I also really like this example from this answer: https://stackoverflow.com/a/1795027/131809

public class Coffee
 {
    private bool _cream;

    public Coffee Make { get new Coffee(); }
    public Coffee WithCream()
    {
      _cream = true;
      return this;
    }
    public Coffee WithOuncesToServe(int ounces)
    {
      _ounces = ounces;
      return this;
    }
 }

var myMorningCoffee = Coffee.Make.WithCream().WithOuncesToServe(16);

Which reminds me, I need a coffee now.

Alex
  • 37,502
  • 51
  • 204
  • 332
  • Thanks for that. Whilst I see why the 'Set' property is there (from a code pov) I don't really understand _why_ it is there. – Stuart Hemming Apr 17 '15 at 09:08
2

return this is not all there is to fluent interfaces. Chaining methods is a simplistic form of building a fluent API, but fluent APIs generally look like DSLs (domain specific languages) and are much, much harder to design.

Take Moq as an example:

new Mock<IInterface>()
    .Setup(x => x.Method())
    .CallBack<IInterface>(Console.WriteLine)
    .Returns(someValue);
  • The Setup method, defined on the type Mock<T>, returns an instance of ISetup<T, TResult>.

  • The Callback method, defined for ICallback<TMock, TResult> returns an instance of IReturnsThrows<TMock,TResult>. Note that ISetup<T, TResult> extends IReturnsThrows<TMock,TResult>.

  • Finally, Returns is defined on IReturns<TMock,TResult> and returns IReturnsResult<TMock>. Also note that IReturnsThrows<TMock,TResult> extends IReturnsResult<TMock>.

All these little nuances are there to force you to call these methods in a particular order, and to forbid you from calling Setup twice in a row, for example. Or from calling Returns before you call Setup.

These details are very important to ensure a good user experience.

To read more on designing fluent interfaces, take a look at Martin Fowler's article on FluentInterface. FluentAssertions is another prime example of how complex the design might get - but also of how much more readable the outcome is.

dcastro
  • 66,540
  • 21
  • 145
  • 155
0

Nope, that's pretty much it.

The idea behind is that you can chain method calls together manipulating internal state as you go. Ultimately the main goal of a Fluent interface is readability, LINQ being a very good example of one.

James
  • 80,725
  • 18
  • 167
  • 237