Wednesday, May 14, 2014

Loan pattern in C#

There is a pattern is Scala called loan pattern. You open a resource, “loan” the resource to another function, and the loaner closes the resource.

Scala

This function expects a file a function. When it's called it creates the resource, executes the function and closes the resource.

def withPrintWriter(file: File, op: PrintWriter => Unit) {
  val writer = new PrintWriter(file)
  try {
    op(writer)
  } finally {
    writer.close()
  }
}

This is how it's called:

withPrintWriter(
  new File("date.txt"),
  writer => writer.println(new java.util.Date)
)

C#

Now I extended the definition with currying:

readonly Func, string>> openFile = 
    path => 
        handler =>
            {
                var reader = new StreamReader(path);
                try
                {
                    return handler(reader);
                }
                finally
                {
                    reader.Close();
                    Console.WriteLine("Stream closed");
                }
            };

Here are two examples on calling the function above:

readonly Func readAllLines = input => input.ReadToEnd();
readonly Func readSingleLine = input => input.ReadLine();

[Fact]
public void LoanPattern_AllText()
{
    var result = openFile("TextFile1.txt")(readAllLines);
    Assert.Equal("This is the test content.\r\nThis is a second line.", result);
}

[Fact]
public void LoanPattern_ReadSingleLine()
{
    var result = openFile("TextFile1.txt")(readSingleLine);
    Assert.Equal("This is the test content.", result);
}

Result

Now the code calling the function (openFile) is much simpler and there is no need for error handling in the caller. Furthermore thanks to currying, even the resource name can be bound in the constructor, hiding the resource initialization as well.

No comments:

Post a Comment