Home » New in .NET 8.0 [3]: Primary constructors in C# 12.0

New in .NET 8.0 [3]: Primary constructors in C# 12.0

by admin
New in .NET 8.0 [3]: Primary constructors in C# 12.0

C# 12.0 was released together with Visual Studio 2022 version 17.8 and .NET 8.0 on November 14, 2023. C# 12.0 is only officially supported by Microsoft from .NET 8.0 onwards (“C# 12.0 is supported only on .NET 8 and newer versions.”). However, you can also use most (but not all!) C# 12.0 language features in older .NET versions including .NET Framework, .NET Core and Xamarin. To do this you have to in the project file (.csproj) to “12.0”.

Advertisement

Dr. Holger Schwichtenberg is Chief Technology Expert at MAXIMAGO, which offers innovation and experience-driven software development, including in highly critical safety-related areas. He is also head of the expert network www.IT-Visions.de, which supports numerous medium-sized and large companies with advice and training in the development and operation of software with 43 renowned experts.

The most significant new feature in C# 12.0 is primary constructors for classes. Old hands among C# developers will remember that this language feature was already available as a prototype for C# 6.0 in 2014, but was then deleted.

Now, six C# versions later, Microsoft is coming back to this in C# 12.0, also against the background of the record types that have been available with primary constructors since C# 9.0:

public record Person(int ID, string Name, string Website = “”);

A primary constructor is a list of parameters immediately after the type name. In C# 12.0 this is also possible for class definitions:

public class Person(int ID, string Name, string Website = “”);

Such a class can exist without a content area (i.e. curly brackets), but it is worthless. Unlike the record types introduced in C# 9.0, the primary constructor does not create public properties in the class, only private fields. If you look at this class with a primary constructor in a decompiler, you will initially see no processing of the parameters in the primary constructor at all:

See also  The meaning of Yellow by Coldplay: what color is love...

public class Person
{
public Person(int ID, string Name, string Website = “”)
{
}
}

This is because the primary constructor parameters are not used at all. We have to class e.g. E.g. extend it with ToString():

public class Person(int id, string name, string website = “”)
{
public string Name { get; set; } = name;
public string Website { get; set; } = website;

public override string ToString()
{
return $”Person #{id}: {Name} -> {Website}”;
}
}

Now we see in the ILSpy decompiler that a private field has been created for the constructor parameter id, but not for name and website, since these only initialized a property and no longer provides direct access to the names from the primary constructor (name and website with a small initial letters!).

No private field is created if you use a constructor parameter only for initialization:

public class Person
{
[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]

private int P;

public string Name { get; set; }

public string Website { get; set; }

public Person(int id, string name, string website = “”)
{
P = id;
Name = name;
Website = website;
base..ctor();
}

public override string ToString()
{
return $”Person #{P}: {Name} -> {Website}”;
}
}

To publicly access the data passed in the primary constructor, one must use the constructor parameters for assignments, see name and website in the following code example. In addition to the Person class, there is a second, derived Author class with a primary constructor:

using System.ComponentModel.DataAnnotations;
using ITVisions;

namespace NET8Konsole.CS12;

///

/// Class with primary constructor ///

public class Person(Guid id, string name) { public string Name { get; set; } = name; public Person() : this(Guid.Empty, “”) { } public override string ToString() { // Use property name here instead of // primary constructor parameter name! // Otherwise you wouldn’t see name changes! return $”Person {id}: {Name}”; } } ///

See also  Einhell cordless lawn mower in a set with grass trimmer, batteries & Co.
/// Derived class with primary constructor ///

public class Autor(Guid id,
string name,
string website) : Person(id, name)
{
public string Website { get; set; } = website;

public override string ToString() {
return $”Autor {id}: {Name} -> {Website}”;
}
}

internal class CS12_PrimaryConstructors_Demo
{
public void Run()
{
var p = new Person();
Console.WriteLine(p.Name);
Console.WriteLine(p.ToString());
var a = new Autor(Guid.NewGuid(), “Dr. Holger Schwichtenberg”,
“www.IT-Visions.de”);
Console.WriteLine(a.Name);
Console.WriteLine(a.Website);
Console.WriteLine(a.ToString());
}
}

Unfortunately, in C# primary constructors do not have the ability to control which visibility the resulting data members of the class should have through the public and private visibilities as in TypeScript constructors.

Likewise, there is no readonly restriction possible that prevents program code in the class from changing the passed value.

(rme)

To home page

You may also like

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Accept Read More

Privacy & Cookies Policy