Primary Constructors for Classes, Collection Literals, Readonly Members for Records, and Default Interface Methods Enhancements.

 

1. Primary Constructors for Classes

Primary constructors provide a concise way to declare constructors directly in the class declaration. This feature simplifies the syntax for creating classes with properties that need to be initialized through constructor parameters.

Example: Primary Constructors for Classes

public class Person(string firstName, string lastName) { public string FirstName { get; } = firstName; public string LastName { get; } = lastName; public void Display() { Console.WriteLine($"Name: {FirstName} {LastName}"); } } class Program { static void Main() { var person = new Person("John", "Doe"); person.Display(); // Output: Name: John Doe } }
  • Explanation: The class Person defines its primary constructor inline with the class declaration. The constructor parameters firstName and lastName are automatically assigned to the properties FirstName and LastName using property initializers. This syntax reduces boilerplate code.

2. Collection Literals

Collection Literals offer a more flexible and concise syntax for initializing collections. This allows you to initialize collections directly with elements in a simpler, cleaner manner.

Example: Collection Literals

using System.Collections.Generic; class Program { static void Main() { var numbers = [1, 2, 3, 4, 5]; // Collection literal for List<int> Console.WriteLine(string.Join(", ", numbers)); // Output: 1, 2, 3, 4, 5 var names = new List<string> { "Alice", "Bob", "Charlie" }; // Traditional syntax Console.WriteLine(string.Join(", ", names)); // Output: Alice, Bob, Charlie } }
  • Explanation: The collection literal syntax [1, 2, 3, 4, 5] simplifies the creation of a List<int>. This shorthand reduces verbosity when initializing collections with predefined elements, though the traditional List<string> initialization is still available.

3. Readonly Members for Records

Records are designed to be immutable by default, but readonly members add another layer of immutability, ensuring that specific members can't be modified after the record is created, even if the record itself is not strictly immutable.

Example: Readonly Members for Records

public record Person { public string FirstName { get; init; } public string LastName { get; init; } public readonly DateTime BirthDate; // Readonly member public Person(string firstName, string lastName, DateTime birthDate) { FirstName = firstName; LastName = lastName; BirthDate = birthDate; } public void Display() { Console.WriteLine($"Name: {FirstName} {LastName}, BirthDate: {BirthDate.ToShortDateString()}"); } } class Program { static void Main() { var person = new Person("John", "Doe", new DateTime(1990, 1, 1)); person.Display(); // Output: Name: John Doe, BirthDate: 1/1/1990 } }
  • Explanation: The BirthDate member is declared as readonly, meaning it can only be set in the constructor and cannot be modified afterward. This ensures that certain properties remain immutable throughout the lifetime of the record, even if other members might be settable via init.

4. Default Interface Methods Enhancements

C# introduced default interface methods in C# 8, allowing interfaces to provide default implementations. Enhancements in newer versions of C# expand this feature, supporting more complex behaviors like overriding default methods in derived interfaces or classes.

Example: Default Interface Methods Enhancements

public interface ILogger { void Log(string message) { Console.WriteLine($"Default Log: {message}"); } void Error(string message) { Console.WriteLine($"Default Error: {message}"); } } public class CustomLogger : ILogger { public void Log(string message) { Console.WriteLine($"Custom Log: {message}"); } } public class AdvancedLogger : CustomLogger, ILogger { // Inheriting default Error method from ILogger } class Program { static void Main() { ILogger logger = new CustomLogger(); logger.Log("Hello, World!"); // Output: Custom Log: Hello, World! ILogger advancedLogger = new AdvancedLogger(); advancedLogger.Error("An error occurred"); // Output: Default Error: An error occurred } }
  • Explanation: In this example, the ILogger interface provides default implementations for both Log and Error methods. The CustomLogger class overrides the Log method, while the AdvancedLogger class inherits the default Error method from the interface. This demonstrates the flexibility and power of default interface methods in allowing default behavior while still permitting customization.

Summary

  1. Primary Constructors for Classes: A shorthand for defining constructors directly within class declarations. It reduces boilerplate code by allowing constructor parameters to be declared inline with the class.
  2. Collection Literals: A more concise syntax for initializing collections, allowing you to create lists or arrays with a simplified literal syntax.
  3. Readonly Members for Records: Ensures immutability for specific members of a record, preventing them from being modified after the record is created, even if other members remain modifiable via the init keyword.
  4. Default Interface Methods Enhancements: Expands the capabilities of default interface methods by supporting more complex scenarios, such as overriding default methods and allowing richer behavior across interfaces and classes.

Post a Comment