0

I have a question about Fluent Interface Builder. I have a simple object like this:

public class Person
{
    public string Name { get; set; }
    public string Surname { get; set; }
    public int Age { get; set; }

    ... other properties
}

and I have a simple UserBuilder class:

public class UserBuilder
{
    private string _name;
    private string _surname;
    private int _age;
    private Gender _gender;

    private UserBuilder(){ }

    public static UserBuilder Create()
    {
        return new UserBuilder();
    }

    public UserBuilder WithName(string name)
    {
        _name = name;
        return this;
    }

    public UserBuilder WithSurname(string surname)
    {
        _surname = surname;
        return this;
    }
    //Other methods......

    public Person Build()
    {
        return new Person
        {
            Name = _name,
            Age = _age,
            Surname = _surname
            ......
        };
    }
}

My questions are:
Is it correct to check the status of the object in the build method? Example:

public Person Build()
{
    // Is it correct??
    if(string.IsNullOrEmpty(_name))
        throw new Exception();

    if(string.IsNullOrEmpty(_surname))
        throw new Exception();

    return new Person
    {
        Name = _name,
        Age = _age,
        Surname = _surname
        ......
    };
}

If it's correct what kind of exception should I throw? ArgumentException?? InvalidOperationException??
If it's not correct, where and how I can validate object created? Thanks a lot.

1

I'd recommend following the fail fast principle, so those checks should be in the "setter" methods, eg:

public UserBuilder WithName(string name)
{
    if(string.IsNullOrEmpty(name)) throw new ArgumentException(nameof(name));

    _name = name;
    return this;
}

Build should then just create the Person object.

Another point is that, if you are going to go to the trouble of providing a builder, then make Person immutable:

public class Person
{
    public Person(string name, string surname, int age)
        => (Name, Surname, Age) = (name, surname, age);

    public string Name { get; }
    public string Surname { get;}
    public int Age { get; }
}
  • Isn't Build() part of the same call chain anyway? I like that tuple assignment arrangement; I didn't know you could do that in C#. – Robert Harvey Jul 5 at 17:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.