Sunday, January 24, 2021

C# 9.0: Positional Records

This post introduces C# 9.0 positional records. Recall C# 9.0 record types were introduced in the post, C# 9.0: Record Types. A positional record is declared with a list of parameters such those shown below in lines 25 to line 29:


The record created contains an auto-property for each parameter in the declaration (PatientProperty, Count, Start, End, and DateRange). Each auto-property has a public access level. Auto-properties have a get and init access specifier (see: C# 9.0: Init Only Setters). The names of the parameters shown above were made uppercase so that the names of the auto-properties would be uppercase following the naming convention for properties.

Five parameters were specified in declaring the Patients record. The compiler creates a corresponding primary constructor taking the same five parameters as arguments. An example of the invocation of the primary constructor is as follows where the factory method, CreateDay, creates an instance of Patients where the parameters are passed at lines 43 through 47:


The auto-property, PatientProperty, is an enumeration also named PatientProperty. Use of the auto-property PatienProperty is shown below being used internally by the Patients class (lines 31, 33, and 35 below):


The PatientProperty property is never explicitly declared as all properties of the record corresponding to the declaration parameters are auto-properties and the compiler auto created each property. 

The PatientProperty enumeration is decorated by the Flags attribute (see FlagsAttribute Class) meaning that the enumerations values can be combined as they are bit fields. Lines 31, 33, and 35 above show the PatientProperty auto-property being used with the bitwise AND operator (&) in order to determine if the Patients in the date range are IsCovid19, IsIcu, or IsVentilator.

The source for this example is follows using screenshots from Visual Studio Code:

The source code in text form is found in Appendix A; Source Code at the end of this post.

Default Constructor

There is no default (parameterless) constructor created by the compiler for a positional record. It is illegal to create a parameterless constructor for a positional record. Below is an example (which will not compile) where the parameterless constructor is created and invoked at lines 47 to 53 using nominal object creation:


The error created while compiling the code above using Visual Studio Code is as  follows:

Appendix A: Source Code

The source code in its entirety is as shown below and of note:

  • There is no constructor explicitly declared for the class as the primary constructor is created by the compiler based on the parameters specified when the record was declared. 
  • The five parameters specified when the record was declared do not have explicit property declarations as the compiler automatically create this properties (auto-properties).
  • Other properties can be declared such as IsIcu, IsCovid19, and IsVentilator. The values for these parameters are computed using auto-properties assigned based on the parameters passed to the primary constructor. 
  • There is no implicit default constructor created for the record.

using System;

namespace HealthDashboard.Models 
{
    public enum DateRangeType 
    {
        Day,
        Week,
        Month,
        Quarter,
        Biannual,
        Year,
        Custom
    }

    [Flags]
    public enum PatientProperty
    {
        Covid19 = 0x1,
        Icu = 0x2,
        Ventilator = 0x4
    }

    public record Patients(
        PatientProperty PatientProperty,
        int Count,
        DateTime Start,
        DateTime End,
        DateRangeType DateRange) 
    {
        public bool IsCovid19 => 
           (0 != (PatientProperty & PatientProperty.Covid19));

        public bool IsIcu  => 
            (0 != (PatientProperty & PatientProperty.Icu));

        public bool IsVentilator => 
             (0 != (PatientProperty & PatientProperty.Ventilator));

        public static Patients CreateDay(
                    PatientProperty patientProperty, 
                    int count, 
                    DateTime start)
        {
            return new (
                    patientProperty,
                    count, 
                    start, 
                    start.AddDays(1), 
                    DateRangeType.Day);
        }                            

        public static Patients CreateWeek(
                    PatientProperty patientProperty, 
                    int count, 
                    DateTime start)
        {
            return new (
                    patientProperty,
                    count, 
                    start, 
                    start.AddDays(7), 
                    DateRangeType.Week);
        }                            

        public static Patients CreateMonth(
                    PatientProperty patientProperty, 
                    int count, 
                    DateTime start)
        {
            return new (
                    patientProperty,
                    count, 
                    start, 
                    start.AddMonths(1), 
                    DateRangeType.Month);
        }                           

        public static Patients CreateQuarter(
                    PatientProperty patientProperty, 
                    int count, 
                    DateTime start)
        {
            return new (
                    patientProperty,
                    count, 
                    start, 
                    start.AddMonths(3), 
                    DateRangeType.Quarter);
        }                            

        public static Patients CreateBiannual(
                    PatientProperty patientProperty, 
                    int count, 
                    DateTime start)
        {
            return new (
                    patientProperty,
                    count, 
                    start, 
                    start.AddMonths(6), 
                    DateRangeType.Biannual);
        }                            

        public static Patients CreateYear(
                    PatientProperty patientProperty, 
                    int count, 
                    DateTime start)
        {
            return new (
                    patientProperty,
                    count, 
                    start, 
                    start.AddYears(1), 
                    DateRangeType.Year);
        }                            

        public static Patients CreateCustom(
                    PatientProperty patientProperty, 
                    int count, 
                    DateTime start,
                    DateTime end)
        {
            return new (
                    patientProperty,
                    count, 
                    start, 
                    end, 
                    DateRangeType.Custom);
       }    
    }
}







No comments :

Post a Comment