Tuples and Deconstruction, Pattern Matching, Local Functions, Out Variables, Ref Locals and Returns, and Expression-Bodied Constructors and Destructors.

 

1. Tuples and Deconstruction

Tuples allow you to return multiple values from a method without needing to define a class or structure. You can use deconstruction to unpack tuple values into individual variables.

Example: Tuples and Deconstruction

class Program { // Method returning a tuple with multiple values static (int sum, int product) Calculate(int a, int b) { return (a + b, a * b); } static void Main() { // Using tuple var result = Calculate(3, 4); Console.WriteLine($"Sum: {result.sum}, Product: {result.product}"); // Output: Sum: 7, Product: 12 // Deconstruction to separate variables (int sum, int product) = Calculate(5, 6); Console.WriteLine($"Sum: {sum}, Product: {product}"); // Output: Sum: 11, Product: 30 } }
  • Explanation: The Calculate method returns a tuple with two values: the sum and product. You can access these values using the tuple’s named fields, or you can deconstruct the tuple directly into separate variables.

2. Pattern Matching

Pattern matching enhances switch statements and expressions by allowing you to match based on types and conditions, not just values. This makes the code more expressive and flexible.

Example: Pattern Matching with switch

class Program { static string CheckType(object obj) { switch (obj) { case int i: return $"Integer: {i}"; case string s when s.Length > 5: return $"Long string: {s}"; case null: return "Null object"; default: return "Unknown type"; } } static void Main() { Console.WriteLine(CheckType(42)); // Output: Integer: 42 Console.WriteLine(CheckType("HelloWorld")); // Output: Long string: HelloWorld Console.WriteLine(CheckType(null)); // Output: Null object Console.WriteLine(CheckType(3.14)); // Output: Unknown type } }
  • Explanation: In this example, pattern matching is used in the switch statement to match objects based on their types (int, string, null) and conditions (e.g., string length). This improves readability compared to traditional type checking and casting.

3. Local Functions

Local functions allow you to define functions inside methods. This helps in organizing code better, especially when the function is only relevant within a particular method.

Example: Local Functions

class Program { static void Main() { int AddNumbers(int x, int y) { return x + y; } int result = AddNumbers(10, 20); Console.WriteLine(result); // Output: 30 } }
  • Explanation: The AddNumbers function is defined inside the Main method as a local function. It is only accessible within Main, making the code more modular and self-contained.

4. Out Variables

C# now allows you to declare out variables inline, directly in the method call. This makes code more concise and reduces the need for separate variable declarations.

Example: Out Variables

class Program { static void ParseInteger(string input) { if (int.TryParse(input, out int result)) { Console.WriteLine($"Parsed successfully: {result}"); } else { Console.WriteLine("Failed to parse."); } } static void Main() { ParseInteger("123"); // Output: Parsed successfully: 123 ParseInteger("abc"); // Output: Failed to parse. } }
  • Explanation: The int.TryParse method uses an out variable (result), declared inline in the if statement. This avoids the need to declare result separately, simplifying the code.

5. Ref Locals and Returns

Ref locals and ref returns allow you to return and work with references to variables, instead of their values. This is useful for performance-sensitive scenarios where you need to modify the original data directly.

Example: Ref Locals and Returns

class Program { static ref int FindNumber(int[] numbers, int target) { for (int i = 0; i < numbers.Length; i++) { if (numbers[i] == target) { return ref numbers[i]; // Return reference to the array element } } throw new Exception("Number not found"); } static void Main() { int[] numbers = { 1, 2, 3, 4, 5 }; ref int numberRef = ref FindNumber(numbers, 3); numberRef = 10; // Modify the original array element through the reference Console.WriteLine(string.Join(", ", numbers)); // Output: 1, 2, 10, 4, 5 } }
  • Explanation: The FindNumber method returns a reference to an element in the numbers array. By using ref returns and locals, we can modify the original array element through the reference, not just a copy of the value.

6. Expression-Bodied Constructors and Destructors

The expression-bodied syntax, previously limited to methods and properties, can also be used for constructors, destructors, and finalizers.

Example: Expression-Bodied Constructors and Destructors

class Person { public string Name { get; } // Expression-bodied constructor public Person(string name) => Name = name; // Destructor (Finalizer) using expression-bodied syntax ~Person() => Console.WriteLine($"{Name} is being finalized."); } class Program { static void Main() { var person = new Person("Alice"); Console.WriteLine(person.Name); // Output: Alice // Destructor will be called when the object is collected by the garbage collector } }
  • Explanation: The constructor is written as a single line using the expression-bodied syntax. The destructor (finalizer) also uses the => syntax to simplify its implementation. This is useful for cases where the logic is simple and fits neatly into a single line.

Summary

  1. Tuples and Deconstruction: Allow methods to return multiple values using tuples, which can be deconstructed into individual variables.
  2. Pattern Matching: Provides more powerful control over switch statements and expressions by matching types and conditions.
  3. Local Functions: Allow functions to be defined within other methods, keeping the code modular and self-contained.
  4. Out Variables: Enable out parameters to be declared inline within method calls, making code more concise.
  5. Ref Locals and Returns: Allow methods to return and work with references, enabling direct modification of data rather than working with copies.
  6. Expression-Bodied Constructors and Destructors: Simplify constructors, destructors, and finalizers using concise expression-bodied syntax.

Post a Comment