I have a `Shift` class that looks like this:

    public class Shift
    {
        public string Name { get; private set; }
        public TimeSpan StartHour { get; private set; }
        public TimeSpan EndHour { get; private set; }

        public TimeSpan Duration => EndHour - StartHour;

        private Shift(string name, TimeSpan startHour, TimeSpan endHour)
        {
            Name = name;
            StartHour = startHour;
            EndHour = endHour;
        }

        private Shift()
        {
        }
    }
Since there are some limitations and restrictions to what `StartHour` && `EndHour` can be I needed some way to validate the input of the class and if it fails - prevent the creation of the object or at least not return it to the user, without throwing an exception because I want to allow the user to re-enter the arguments if some of them were invalid.

Than I created an interface and some derived classes to be injected during the construction of the object:

    public interface IShiftValidator
    {
        Exception FailedValidationException { get; }
        string FailedValidationMessage { get; }
        bool IsValid(Shift shiftToValidate);
    }

    public class ShiftRangeValidator : IShiftValidator
    {
        public Exception FailedValidationException { get; private set; }
        public string FailedValidationMessage { get; private set; } = string.Empty;

        public bool IsValid(Shift shiftToValidate)
        {
            if (shiftToValidate.Duration.TotalMinutes <= 0)
            {
                FailedValidationException = new ArgumentOutOfRangeException(nameof(shiftToValidate.Duration));
                FailedValidationMessage = "Shift's duration cant be less than 1 minute.";
                return false;
            }
            if (shiftToValidate.Duration.TotalHours > SharedSettings.MaximumShiftHours)
            {
                FailedValidationException =
                    new ArgumentOutOfRangeException(nameof(shiftToValidate.Duration));
                FailedValidationMessage = "Shift's duration cant be longer than the maximum allowed hours.";
                return false;
            }
            return true;
        }
    }

After that I implemented the builder pattern as a nested class in the `Shift` class, so I can make the constructor of the class private and construct the object fully in the builder class:

    public class ShiftBuilder
    {
        private Shift _shift;

        public ShiftBuilder()
        {
            _shift = new Shift();
        }

        public ShiftBuilder WithName(string name)
        {
            _shift.Name = name;   
            return this;
        }

        public ShiftBuilder WithStartHour(TimeSpan startHour)
        {
            _shift.StartHour = startHour;
            return this;
        }

        public ShiftBuilder WithEndHour(TimeSpan endHour)
        {
            _shift.EndHour = endHour;
            return this;
        }

        public Shift Build(IEnumerable<IShiftValidator> validators)
        {
            if (validators != null)
            {
                foreach (var shiftValidator in validators)
                {
                    if (!shiftValidator.IsValid(_shift))
                    {
                        if (!string.IsNullOrEmpty(shiftValidator.FailedValidationMessage))
                        {
                            MessageBox.Show(shiftValidator.FailedValidationMessage);
                        }
                        throw shiftValidator.FailedValidationException;
                    }
                }
            }
            Shift shift = _shift;
            _shift = null;
            return shift;
        }
    }

Here's an example usage:

    Shift.ShiftBuilder shiftBuilder = new Shift.ShiftBuilder();
    var a = shiftBuilder.WithName("Test")
        .WithStartHour(new TimeSpan(12, 0, 0))
        .WithEndHour(new TimeSpan(24, 0, 0))
        .Build(new[] { new ShiftRangeValidator() });

    var b = shiftBuilder.Build(null); // null
    var c = shiftBuilder.Build(new[] {new ShiftRangeValidator()}); // crash

I have few concerns:

1. Is it clear that you're unable to reuse the same `ShiftBuilder` twice?
2. Is `IShiftValidator` good as it is or should I separate it in few smaller interfaces?