Modern C# Features – Interview Questions
1. What are Nullable Reference Types?
Nullable Reference Types (C# 8.0) help identify possible null reference errors during compilation.
By default, when nullable reference types are enabled, a reference type is considered non-nullable unless declared with ?.
Example
#nullable enable
string name = "John"; // Non-nullable
string? city = null; // Nullable
Console.WriteLine(name);
Console.WriteLine(city?.Length);
Explanation:
-
stringindicates that the variable should not containnull. -
string?explicitly allowsnull. -
?.safely accesses a member when the object is not null. -
The compiler generates warnings for possible null-reference problems.
Key Points
-
Introduced in C# 8.0.
-
Helps prevent
NullReferenceException. -
Provides compile-time warnings, not runtime enforcement.
-
Enable using
<Nullable>enable</Nullable>in.csproj.
2. What is Pattern Matching in C#?
Pattern matching checks whether a value matches a particular type, constant, range, or structure.
It reduces complex if-else conditions.
Example
int age = 25;
if (age is >= 18 and <= 60)
{
Console.WriteLine("Eligible");
}
else
{
Console.WriteLine("Not Eligible");
}
Output:
Eligible
Explanation:
-
isperforms pattern matching. -
>= 18checks the minimum age. -
andcombines two conditions. -
<= 60checks the maximum age.
Key Points
-
Supports type, constant, relational, property, and other patterns.
-
Uses keywords such as
is,and,or, andnot. -
Reduces lengthy conditional statements.
-
Useful for validation and business rules.
3. What are Switch Expressions?
A switch expression (C# 8.0) is a shorter way to evaluate multiple conditions and return a value.
Unlike a traditional switch statement, it directly produces a result.
Example
int status = 2;
string result = status switch
{
1 => "Pending",
2 => "Approved",
3 => "Rejected",
_ => "Unknown"
};
Console.WriteLine(result);
Output:
Approved
Explanation:
-
status switchevaluates the value. -
=>specifies the result for each matching pattern. -
_represents the default case. -
No
breakstatement is required.
Key Points
-
Introduced in C# 8.0.
-
More concise than traditional
switchstatements. -
Returns a value directly.
-
Supports pattern matching.
-
Useful for status mapping and business rules.
4. What Are init-Only Properties?
init-only properties (C# 9.0) allow property values to be assigned during object initialization but not modified afterward.
Example
public class Employee
{
public int Id { get; init; }
public string Name { get; init; } = "";
}
// Object initialization
Employee emp = new Employee
{
Id = 101,
Name = "John"
};
Console.WriteLine(emp.Name);
// emp.Name = "David"; // Compile-time error
Explanation:
-
initallows setting values during initialization. -
After initialization, reassignment is not allowed.
-
Helps create objects with stable property values.
Key Points
-
Introduced in C# 9.0.
-
Supports initialization-time immutability.
-
Commonly used with records and DTOs.
-
Unlike
set,initprevents later property reassignment. -
Does not make referenced objects deeply immutable.
5. What Is the required Keyword?
The required keyword (C# 11) ensures that a property or field must be initialized when creating an object, unless a constructor explicitly satisfies the requirement.
Example
public class Employee
{
public required string Name { get; init; }
public int Age { get; set; }
}
Employee emp = new Employee
{
Name = "John"
};
Console.WriteLine(emp.Name);
Explanation:
-
Namemust be initialized. -
Ageis optional. -
If
Nameis not initialized, the compiler reports an error.
Employee emp = new Employee();
// Compile-time error: Name is required
Key Points
-
Introduced in C# 11.
-
Enforces member initialization at compile time.
-
Works with both
setandinit. -
Useful for DTOs, configuration objects, and domain models.
-
Does not automatically prevent assigning
nullat runtime.
6. What Are Primary Constructors?
Primary constructors (C# 12) allow constructor parameters to be declared directly in the class or struct declaration.
They reduce constructor boilerplate.
Example
public class Employee(int id, string name)
{
public void Display()
{
Console.WriteLine($"{id} - {name}");
}
}
// Usage
Employee emp = new Employee(101, "John");
emp.Display();
Output:
101 - John
Explanation:
-
idandnameare primary constructor parameters. -
Values are passed while creating the object.
-
Parameters can be accessed inside instance members.
-
No separate constructor declaration is required.
Key Points
-
Introduced for classes and structs in C# 12.
-
Reduces boilerplate code.
-
Useful for Dependency Injection.
-
Primary constructor parameters are not automatically public properties.
-
Records also support primary constructor syntax, with different property-generation behavior.
ASP.NET Core Example:
public class EmployeeService(
ILogger<EmployeeService> logger)
{
public void Process()
{
logger.LogInformation("Processing employee");
}
}
This is useful for constructor-based Dependency Injection.
7. What Are Collection Expressions?
Collection expressions (C# 12) provide a simpler syntax for creating arrays, lists, spans, and other supported collection types.
They use square brackets [].
Example
// Traditional syntax
int[] numbers1 = new int[] { 10, 20, 30 };
// Collection expression
int[] numbers2 = [10, 20, 30];
// List
List<string> names = ["John", "David", "Peter"];
foreach (string name in names)
{
Console.WriteLine(name);
}
Output:
John
David
Peter
Explanation:
-
[10, 20, 30]creates an array using the declared target type. -
["John", "David", "Peter"]initializes aList<string>. -
Collection expressions reduce unnecessary syntax.
Key Points
-
Introduced in C# 12.
-
Uses
[]syntax. -
Supports arrays, lists, spans, and compatible collection types.
-
Supports spread elements using
...
Example:
int[] first = [1, 2];
int[] second = [3, 4];
int[] combined = [..first, ..second];
// Result: 1, 2, 3, 4
Quick Interview Revision
|
Feature |
C# Version |
Main Purpose |
|---|---|---|
|
Nullable Reference Types |
C# 8 |
Reduce null-reference errors |
|
Pattern Matching |
C# 7 onward |
Simplify conditional checks |
|
Switch Expressions |
C# 8 |
Return values using concise switch syntax |
|
|
C# 9 |
Prevent reassignment after initialization |
|
|
C# 11 |
Enforce initialization |
|
Primary Constructors |
C# 12 |
Simplify constructor declarations |
|
Collection Expressions |
C# 12 |
Simplify collection initialization |
Important interview differences:
-
setvsinit:setallows modification later;initallows assignment only during initialization. -
requiredvsinit:requiredenforces initialization;initrestricts when assignment can occur. -
Traditional switch vs switch expression: Traditional switch executes statements; a switch expression produces a value.
-
Normal constructor vs primary constructor: A primary constructor reduces boilerplate by placing parameters in the type declaration.