Introduction
C# 9.0 has made history by bringing changes in the compiler and has created a relationship between language and framework. It also supports .NET 5 versions. Hope the readers must have learned my previous article, use of Delegates in C# programming.
With this new version of C# 9.0 we got greater clarity and unfussiness in common coding scenarios, and C# 9.0 which definitely helps developers a lot especially, in the data handling sector, it supports terse and unchallengeable views of data shapes. The Web Data extraction activities would be definitely easier than before because of data shape presentation.
Following are some important new features which will be valuable for you.
Init only setters
var candidate= new candidate { FirstName = "Paul", LastName = "Colloingwood" };
Please note that the Object initializers also lower the burden of writing so many construction boilerplates by facilitating to write of some properties only!
public class candidate { public string? FirstName { get; set; } public string? LastName { get; set; } }
Here, the ‘init’ accessor that is a newer variant of the ‘set’ accessor which can only be called at the time of object initialization as follows:
public class candidate { public string? FirstName { get; init; } public string? LastName { get; init; } }
I Hope, this new object initializer will help you more than the older one.
Record Types
Record types are introduced as a reference for synthesized methods to obtain value semantics for similarity. As usual, records are incontrovertible by default.
When we define a record type, the compiler synthesizes different methods; some methods are given below for your ready reference.
- With-expressions
With-expressions incorporate object initializer syntax to mention the difference between the new object and the old object. You can identify various properties.
The with-expression works by truly copying the complete state of the old object into a new one, then changing it as per the object initializer. The properties must possess a ‘set’ or ‘init’ accessor to get altered in a ‘with-expression’
var Candidate = new Candidate { FirstName = "Paul", LastName = "Collingwood" }; var otherCandidate = person with { LastName = " Collingwood”};
- Value-based equality
Generally, all objects inherit a virtual method i.e., ‘Equals(object)’ from the object class. This is utilized as the source for the static method ‘Object.Equals(object, object)’ while both parameters are not null.
This time ‘Structs’ override this to achieve "value-based equality", matching every field of the struct through calling ‘Equals’ on them recursively. Records do a similar act.
This indicates that according to their "value-ness" two record objects could be equal with each other even though they’re not the same object.
For illustration, if we update the last name of the modified candidate back again:
var originalCandidate = otherCandidate with { LastName = "Smith" };
Often, Value equality and variability don’t engage well. One issue is that modifying values could cause the result of GetHashCode() to alter over time, which is adverse if the object is hoarded in a hash table! We allow alterable records, but we depress them unless you have thought through the cost!
- Inheritance
With C# 9.0, the records can be inherited from other records:
public record Student : Candidate { public int ID; }
With-expressions and value equality work fruitfully with record inheritance, in that they take the entire runtime object into account, not only the record type that it’s basically acknowledged by.
For example: create a Student but store it in a Candidate variable:
Candidate student = new Student { FirstName = "Paul", LastName = "Collingwood", ID = 1 };
The ‘with-expression’ will copy the entire object and keep the runtime type:
var otherStudent = student with { LastName = " Collingwood " }; WriteLine(otherStudent is Student); // true
In the same way, value equality ensures the two objects have a similar runtime type, and then matches their all-state:
Candidate similarStudent = new Student { FirstName = "Pau", LastName = "Smith", ID = 2 }; WriteLine(student != similarStudent); //true, since ID's are different
- Positional records
Sometimes it’s valuable to have a more positional approach to a record, where its contents are specified through the constructor point of view and can be accessed with positional deconstruction. It’s flawlessly possible to state our own constructor and deconstructor in a record:
public record Person { public string FirstName { get; init; } public string LastName { get; init; } public Candidate(string firstName, string lastName) => (FirstName, LastName) = (firstName, lastName); public void Deconstruct(out string firstName, out string lastName) => (firstName, lastName) = (FirstName, LastName); }
But the shorter syntax can be used for expressing exactly the same thing (modulo casing of parameter names):
public record Person(string FirstName, string LastName); This declares the public init-only auto-properties and the constructor and the deconstructor, so that you can write: var person = new Candidate("Paul", "Collingwood"); // positional construction var (f, l) = Candidate; // positional deconstruction
If you don’t wish the auto-generated property you can mention your own customized property of a similar name instead, and the generated constructor and deconstructor will surely use that one.
public record Candidate(string FirstName, string LastName) { protected string FirstName { get; init; } = FirstName; } A positional record can call a base constructor like this: public record Student(string FirstName, string LastName, int ID) : Person(FirstName, LastName);
Top-level statements
This feature reduces unnecessary coding as followings
Older Coding sample before C# 9.0
using System; namespace HelloWorld { class Program { static void Main(string[] args) { Console.WriteLine("great World!"); } } }
New Coding sample in C# 9.
using System; Console.WriteLine("great World!");
Or in one line
System.Console.WriteLine("great World!");
But remember; if you have one file in your specific application, you may go for top-level statements. If the compiler detects top-level statements in multiple numbers of source files, it will be an error. It could be also an error if you join top-level statements with a program entry point method, especially the Main method. It means, one file carries the statements that would generally be in the Main method of a Program class.
One of the most popular uses for this feature is making teaching materials.
4. Pattern matching enhancements
You’ll get the following types of pattern matching improvements.
- Type patterns- match a type variable
- Conjunctive patterns (and patterns)- need two patterns to match
- Parenthesized patterns impose the preference of pattern combinations
- Disjunctive patterns (Or Pattern) need anyone pattern to match
- Negated patterns (negative pattern) need a pattern which doesn’t match
- Relational patterns need the conditional input which is less than, greater than, greater than or equal, and less than or equal, to a given constant.
Post A Comment:
0 comments: