Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c#

.net

c#-9.0

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);
    }
}
like image 327
Pavel Voronin Avatar asked Oct 11 '20 21:10

Pavel Voronin


People also ask

What is a positional record in C#?

Records in C# 9.0 provide positional syntax to declare and initialize property values of an instance. The compiler makes the properties public init-only auto-implemented when the user employs positional syntax to declare and initialize properties.

What does the C# record keyword do?

Beginning with C# 9, you use the record keyword to define a reference type that provides built-in functionality for encapsulating data. C# 10 allows the record class syntax as a synonym to clarify a reference type, and record struct to define a value type with similar functionality.

Can record implement interface C#?

It's legal to implement an interface with a record.

What is record type in C# 9?

C# 9 introduces records, a new reference type that you can create instead of classes or structs. C# 10 adds record structs so that you can define records as value types. Records are distinct from classes in that record types use value-based equality.


1 Answers

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);
}
like image 52
JoeH Avatar answered Oct 19 '22 22:10

JoeH