How do I define additional initialization logic for the positional record?

2.4k views Asked by At

I would like to validate parameters used for record initialization and thro, if validation fails. For regular class I could use constructor for that, but how should I do it with records?

For regular classes I could also have private constructor and public static factory method which returned either error or valid instance, but it looks like there is no way to make record's primary constructor private.

For non-positional record it is like with any other class:

public record Person
{
    public string FirstName {get; init;}
    public string LastName {get; init;}
    
    public Person (string firstName, string lastName)
    {
        (FirstName,LastName) = (firstName, lastName);
    }
}
1

There are 1 answers

0
JoeH On

Adding to the comments above, you can hide the primary constructor when using a factory method by making the record abstract, and adding a private nested class that extends it.

Unlike a traditional class with a private constructor, it's still possible for someone to extend your record. But this does prevent consumers from bypassing the factory on accident.

public abstract record Person(string FirstName, string LastName)
{
  public static Person Create(string FirstName, string LastName)
  {
    // ... validate arguments ...

    return new PersonImpl(FirstName, LastName);
  }

  private record PersonImpl(string FirstName, string LastName) 
    : Person(FirstName, LastName);
}