Iron Academy Logo
Learn C#

Understanding C# Properties

Tim Corey
9m 50s

C# 11, introduced with .NET 7, has brought an exciting addition to properties: the required keyword. In this article, we'll explore C# properties, using examples from Tim Corey’s concise video tutorial on ".NET 7 Update: Required Properties in 10 Minutes or Less". We'll break down everything from the basics of properties to the new required keyword and how it helps enforce initialization rules.

C# Properties

In C#, properties allow you to encapsulate fields and manage access to an object's class data members. They are commonly used to ensure data integrity while allowing external access. The private string name is an automatically implemented property with read only properties to ensure data encapsulation. This only allows user to read the property value without writing to it. It is achieved by using automatically implemented properties. Public string properties often utilize special methods called accessors to manipulate class members efficiently. A static property in C# can be accessed without instantiating the class, offering a unique way to manage property values.

Here’s how Tim sets up a simple property example to demonstrate.

Creating a Console Application

First, Tim starts with a basic .NET 7 console application using C# 11. This version introduces the required keyword, which isn’t available in previous versions of .NET.

Defining a Simple Model

Tim creates a PersonModel class with properties for FirstName and LastName:

public class PersonModel {
    public string FirstName { get; set; }
    public string LastName { get; set; }
}
public class PersonModel {
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

These properties allow PersonModel to store first and last names. However, without additional setup, FirstName and LastName could potentially be left uninitialized, leading to null values.

Using Constructors to Ensure Initialization

A common way to ensure that properties are always initialized is through a constructor. In Tim’s example, he adds a constructor to the base class of PersonModel that requires both FirstName and LastName:

public PersonModel(string firstName, string lastName)
{
    FirstName = firstName;
    LastName = lastName;
}
public PersonModel(string firstName, string lastName)
{
    FirstName = firstName;
    LastName = lastName;
}

This approach enforces that whenever a PersonModel object is created, both name property and properties must be provided. If we were to try creating a the class Person.Model without specifying these values, the compiler would flag it as an error.

Nullable Context

Starting with .NET 6 and C# 10, C# introduced nullable reference types. This means that properties need to be either initialized or explicitly marked as nullable using a ?. For instance, if FirstName and LastName can be null, we would define them as follows:

public string? FirstName { get; set; }
public string? LastName { get; set; }
public string? FirstName { get; set; }
public string? LastName { get; set; }

In Tim’s example, however, we assume FirstName and LastName should always be non-null. For this he created an empty constructor and initialized the properties with a default value. At 3:00, Tim adds a ? nullable operator to these properties when he tires to use empty constructor logic.

Introducing the required Keyword

While constructors can enforce initialization, C# 11 introduces the required keyword, making it easier to ensure that specific properties are set. With required, you can mark individual properties as required, which means they must be assigned a value during object initialization.

Setting Up required Properties

To make FirstName and LastName required properties, Tim at 4:15 modifies the PersonModel class as follows:

public class PersonModel {
    public required string FirstName { get; set; }
    public required string LastName { get; set; }
}
public class PersonModel {
    public required string FirstName { get; set; }
    public required string LastName { get; set; }
}

By marking these static properties with required, the compiler will now enforce that they are set either through an object initializer or a constructor. This is useful because it lets you require specific properties without needing to create a constructor.

Example Usage with Required Properties

Now, we can create and initialize PersonModel as follows:

PersonModel person = new () { FirstName = "Tim", LastName = "Corey" };
PersonModel person = new () { FirstName = "Tim", LastName = "Corey" };

If we omit FirstName or LastName, the compiler will flag an error, prompting us to initialize these required properties.

Using required with Constructors

Tim demonstrates a case where both required properties and constructors are used. In situations where you have a constructor that sets required properties, C# needs to ensure that those properties are still initialized when the constructor is called.

In such cases, the sets required members attribute can be used to signal that the constructor fulfills the required conditions. Here’s how Tim applies it:

[SetsRequiredMembers]
public PersonModel() 
{
    FirstName = "Test";
    LastName = "Test";
}

[SetsRequiredMembers]
public PersonModel(string firstName, string lastName)
{
    FirstName = firstName;
    LastName = lastName;
}
[SetsRequiredMembers]
public PersonModel() 
{
    FirstName = "Test";
    LastName = "Test";
}

[SetsRequiredMembers]
public PersonModel(string firstName, string lastName)
{
    FirstName = firstName;
    LastName = lastName;
}

Adding sets required members informs the compiler that these properties will be set within the constructor, avoiding initialization errors. This feature helps prevent accidental omissions while allowing flexibility in how properties are initialized. Now you can set the properties by any of the following methods when creating Person class object:

Understanding Csharp Properties 1 related to Using required with Constructors

Why required Properties Are Useful

Tim explains the new required keyword streamlines the process of ensuring that properties are always set. Instead of needing constructors for set method in every case or risking unset properties, we now have a straightforward way to require specific values directly in the property declaration.

This feature shines in data models where certain fields are mandatory and can help catch issues early in the development process by preventing runtime null errors.

Additional Properties Example

Tim then added an optional property, Email, which can be nullable:

public string? Email { get; set; }
public string? Email { get; set; }

Because it’s not marked with required, the Email property can remain unset without causing a compiler error. With this example Tim demonstrated the flexibility it allows for a class program with clear distinction between essential and optional data fields without changing the code while creating the object.

Conclusion

The addition of required properties in C# 11 is a valuable feature for developers, ensuring that essential properties are always initialized. Tim Corey’s video provides an excellent introduction to this feature and demonstrates how it works within a console application. By combining the required keyword with object initializers and constructors, we can create more robust and safer data models in C#. For more informative tutorials, please visit Tim's YouTube Channel.