#1,211 – C# 6.0 – Adding Implementation for a Primary Constructor

NOTE: Primary constructors will not be shipping in C# 6.0, after all.  They were implemented in the language, but did not yet have appropriate downstream work done in time for the release of 6.0 (i.e. in Visual Studio and debugger).  Thanks to Steve Hall for pointing this out.  –SPS, 23Oct14

A primary constructor in C# 6.0 allows declaring constructor parameters as part of the type declaration and then using those parameters within auto-property initializers.

You can optionally include an implementation body for the primary constructor, typically at the start of the type.  The implementation includes a code block without any method name or parameters.

Below, the primary constructor implementation derives the value of one property from the name parameter and does some validation on the age parameter.

    public class Dog(string name, int age)
    {
        {
            Name = name + " the Dog";
            if (age > 20)
                throw new ArgumentException("Age too large");
        }

        public string OrigName { get; } = name;
        public string Name { get; protected set; }
        public int Age { get; set; } = age;
    }

1211-001

Advertisements

#1,210 – C# 6.0 – Primary Constructors

NOTE: Primary constructors will not be shipping in C# 6.0, after all.  They were implemented in the language, but did not yet have appropriate downstream work done in time for the release of 6.0 (i.e. in Visual Studio and debugger).  Thanks to Steve Hall for pointing this out.  –SPS, 23Oct14

C# 6.0 introduces the notion of a primary constructor–a constructor defined as part of the type declaration, rather than as a separate method.

Consider the C# 5.0 example below, with a traditional constructor that initializes a couple of properties.  (Note that Name property is not immutable, but only protected).

    public class Dog
    {
        public Dog(string name, int age)
        {
            Name = name;
            Age = age;
        }

        public string Name { get; protected set; }
        public int Age { get; set; }
    }

The primary constructor syntax allows us to simplify this code, moving the constructor into the class declaration.  We can then use auto-property initializers that reference the constructor’s parameters.

    public class Dog(string name, int age)
    {
        public string Name { get; protected set; } = name;
        public int Age { get; set; } = age;
    }

This second code fragment behaves exactly like the first.

#1,208 – C# 6.0 – Auto-Property Initializers Can Be Any Expression

An auto-property initializer, used to initialize the value of an auto-implemented property, can be any expression.  This includes the result of a method call.

Below, we initialize the value of the SecretName property to a value returned by the static function generateSecreteName.

    public class Dog
    {
        public string Name { get; set; }

        // DogCreationTime is immutable
        public DateTime DogCreationTime { get; } = DateTime.Now;

        public string SecretName { get; } = generateSecretName();

        public Dog(string name)
        {
            Name = name;
        }

        private static string generateSecretName()
        {
            Random rand = new Random();
            int numLetters = rand.Next(4, 13);  // 4-12 characters
            string name = "";
            for (int i = 1; i <= numLetters; i++)
                name = name + (char)('a' + rand.Next(0, 26));

            return name;
        }
    }

#1,207 – C# 6.0 – Auto-Property Initializers for Read-Only Properties

Prior to C# 6.0, if you wanted a read-only (immutable) property, you’d typically use a read-only backing field that is initialized in the constructor, as shown below.

    public class Dog 
    {
        public string Name { get; set; }

        // DogCreationTime is immutable
        private readonly DateTime creTime;
        public DateTime DogCreationTime 
        {
            get { return creTime; }
        }

        public Dog(string name)
        {
            Name = name;
            creTime = DateTime.Now;
        }
    }

In C# 6.0, you can use auto-implemented properties to implement a read-only property.  You do this by using an auto-property initializer.  The result is much cleaner than the above example, where we had to explicitly declare a backing field.

    public class Dog
    {
        public string Name { get; set; }

        // DogCreationTime is immutable
        public DateTime DogCreationTime { get; } = DateTime.Now;

        public Dog(string name)
        {
            Name = name;
        }
    }

#1,206 – C# 6.0 – Auto-Property Initializers

C# 3.0 introduced auto-implemented properties.

Older syntax:

private string name = "default";
public string Name
{
    get { return name; }
    set { name = value; }
}

Improved syntax, using auto-implemented properties:

public string Name { get; set; }

The new syntax provided no mechanism for specifying a default property value. To specify a default value, you either needed to go back to using an explicit backing variable or to set the default value from within a constructor.

C# 6.0 supports specifying default values for auto-implemented properties, as shown below.

        public string Name { get; set; } = "default";

#1,205 – C# 6.0 – Using the Null-Conditional when Invoking a Delegate

When you fire an event (by invoking a delegate), you typically need to check for null before invocation.  This avoids a null reference exception if there are no subscribers to the event.

    public class Dog
    {
        public Dog(string name, int age)
        {
            Name = name;
            Age = age;
        }

        public event EventHandler<string> NameChange;

        private string name;
        public string Name
        {
            get { return name; }
            set
            {
                if (value != name)
                {
                    name = value;

                    // Check for null before invocation
                    if (NameChange != null)
                    {
                        NameChange(this, name);
                    }
                }
            }
        }

        public int Age { get; set; }
    }

(The above pattern is not thread-safe).

An alternative pattern is to declare the event with a null handler, so that there is always at least one handler on the invocation list. (This is thread-safe).

In C# 6.0, we can use the null-conditional to invoke a delegate.

                    NameChange?.Invoke(this, name);

#1,204 – C# 6.0 – Using Null-Conditional with Indexer

The new null-conditional operator in C# 6.0 allows checking for null and de-referencing a variable in a single step.

You can use the null-conditional operator with dot (.) notation, to access an object’s properties or to invoke a method.  You can also use the null-conditional with an indexer, as shown below.  The expression returns the value returned by the indexer if the variable is non-null, or returns null if the variable is null.

            string sTest = "Howdy";

            char? thirdChar = sTest?[2];   // 'w'

            sTest = null;
            thirdChar = sTest?[2];   // null

            sTest = "Ho";
            thirdChar = sTest?[2];   // throws IndexOutOfRangeException

Notice that the null-conditional operator protects you from de-referencing a null pointer, but does not protect you from using an index that is longer than the string length.