Daily Knowledge Drop
Coming with C# 11 (being released later this year, coinciding with the .NET 7 release) the compiler will now ensure that fields on a struct will be initialized to their default value
if not explicitly set.
With the current, and prior C# versions, all fields on a struct need to explicitly be set when a struct instance is initialized using a defined constructor.
C# 10 and prior
Consider a Song struct, which contains a number of properties related to a Song:
public struct Song
{
public int Id { get; init; }
public string Name { get; init; }
// this property is required to have
// a default value
public string Artist { get; init; } = "Unavailable";
// this property is required to have
// a default value
public int SongLength { get; init; } = 0;
// As this constructor doesn't set all properties
// those unset properties need an explicit default value
public Song(int id, string name)
{
Id = id;
Name = name;
}
public Song(int id, string name, string artist, int length)
{
Id = id;
Name = name;
Artist = artist;
SongLength = length;
}
public override string ToString() => $"{Id}: Song with name '{Name}' " +
$"by '{Artist}' is {SongLength} seconds long";
}
In the above, the Artist and SongLength properties need to explicitly have a default value set
, as there is a constructor which does not set them.
If the default values are removed:
public string Artist { get; init; }
public int SongLength { get; init; }
then a compiler error will occur:
Auto-implemented property 'Song.Artist' must be fully assigned before
control is returned to the caller. Consider updating to language
version '11.0' to auto-default the property.
Auto-implemented property 'Song.SongLength' must be fully assigned
before control is returned to the caller. Consider updating to language
version '11.0' to auto-default the property.
The error even has a suggestion on how to resolve the issue (assuming you have C# 11 preview version installed).
For completeness, here is an example of using the above struct:
var song = new Song(1, "Everlong", "Foo Fighters", 469);
Console.WriteLine(song);
var halfSong = new Song(1, "Everlong");
Console.WriteLine(halfSong);
var defaultSong = default(Song);
Console.WriteLine(defaultSong);
var blankSong = new Song();
Console.WriteLine(blankSong);
with the output:
1: Song with name 'Everlong' by 'Foo Fighters' is 469 seconds long
1: Song with name 'Everlong' by 'Unavailable' is 0 seconds long
0: Song with name '' by '' is 0 seconds long
0: Song with name '' by '' is 0 seconds long
From the output, one can see that when calling one of the defined constructors
, all the properties need to be explicitly set
- either in the constructor itself, or with a default value. However when using one of the other techniques to instantiate
, the property values will be set to the type's default value
.
C# 11
When using C# 11 (currently this means having a preview version of .NET7 installer, and updating the csproj file to contain <LangVersion>preview</LangVersion>
), the struct can be updated to be as follows:
public struct Song
{
public int Id { get; init; }
public string Name { get; init; }
// now these properties don't require
// a default value
public string Artist { get; init; }
public int SongLength { get; init; }
public Song(int id, string name)
{
Id = id;
Name = name;
}
public Song(int id, string name, string artist, int length)
{
Id = id;
Name = name;
Artist = artist;
SongLength = length;
}
public override string ToString() => $"{Id}: Song with name '{Name}' " +
$"by '{Artist}' is {SongLength} seconds long";
}
Now, when instantiated, not all properties of the struct need to be explicitly set
.
Executing the same sample code as above:
var song = new Song(1, "Everlong", "Foo Fighters", 469);
Console.WriteLine(song);
var halfSong = new Song(1, "Everlong");
Console.WriteLine(halfSong);
var defaultSong = default(Song);
Console.WriteLine(defaultSong);
var blankSong = new Song();
Console.WriteLine(blankSong);
with the output:
1: Song with name 'Everlong' by 'Foo Fighters' is 469 seconds long
1: Song with name 'Everlong' by '' is 0 seconds long
0: Song with name '' by '' is 0 seconds long
0: Song with name '' by '' is 0 seconds long
When calling a defined constructor which doesn't set all properties, the unset properties will be set to the type's default value
.
Notes
A minor update to the language, but which will result in a more familiar, intuitive and expected experience for the experienced C# developer, which have worked with previous versions of the the runtime, and are familiar with the behavior of classes.
References
Daily Drop 160: 14-09-2022
At the start of 2022 I set myself the goal of learning one new coding related piece of knowledge a day.
It could be anything - some.NET / C# functionality I wasn't aware of, a design practice, a cool new coding technique, or just something I find interesting. It could be something I knew at one point but had forgotten, or something completely new, which I may or may never actually use.
The Daily Drop is a record of these pieces of knowledge - writing about and summarizing them helps re-enforce the information for myself, as well as potentially helps others learn something new as well.On This Page