C# – Do Exceptions Make Pure Methods Impure?

cfunctional programmingpure-function

The following code examples provide context to my question.

The Room class is initialized with a delegate. In the first implementation of the Room class, there are no guards against delegates that throw exceptions. Such exceptions will bubble up to the North property, where the delegate is evaluated (note: the Main() method demonstrates how a Room instance is used in client code):

public sealed class Room
{
    private readonly Func<Room> north;

    public Room(Func<Room> north)
    {
        this.north = north;
    }

    public Room North
    {
        get
        {
            return this.north();
        }
    }

    public static void Main(string[] args)
    {
        Func<Room> evilDelegate = () => { throw new Exception(); };

        var kitchen = new Room(north: evilDelegate);

        var room = kitchen.North; //<----this will throw

    }
}

Being that I'd rather fail upon object creation rather than when reading the North property, I change the constructor to private, and introduce a static factory method named Create(). This method catches the exception thrown by the delegate, and throws a wrapper exception, having a meaningful exception message:

public sealed class Room
{
    private readonly Func<Room> north;

    private Room(Func<Room> north)
    {
        this.north = north;
    }

    public Room North
    {
        get
        {
            return this.north();
        }
    }

    public static Room Create(Func<Room> north)
    {
        try
        {
            north?.Invoke();
        }
        catch (Exception e)
        {
            throw new Exception(
              message: "Initialized with an evil delegate!", innerException: e);
        }

        return new Room(north);
    }

    public static void Main(string[] args)
    {
        Func<Room> evilDelegate = () => { throw new Exception(); };

        var kitchen = Room.Create(north: evilDelegate); //<----this will throw

        var room = kitchen.North;
    }
}

Does the try-catch block render the Create() method impure?

Best Answer

Yes. That is effectively an impure function. It creates a side-effect: program execution continues somewhere other than the place to which the function is expected to return.

To make it a pure function, return an actual object that encapsulates the expected value from the function and a value indicating a possible error condition, like a Maybe object or a Unit of Work object.