C# tutorials > Modern C# Features > C# 6.0 and Later > Explain target-typed conditional expressions with an example.

Explain target-typed conditional expressions with an example.

Target-typed conditional expressions, introduced in C# 9.0, simplify code by allowing the compiler to infer the type of a conditional expression based on the target type to which it's being assigned. This eliminates redundant type specifications, leading to cleaner and more readable code.

Basic Example

In this simple example, if isEnabled is true, message will be assigned "Enabled"; otherwise, it will be assigned "Disabled". The type of the conditional expression is inferred to be string because message is a string.

string message = (isEnabled) ? "Enabled" : "Disabled";

Target-Typed Conditional Expression Demonstration

In pre-C# 9.0 versions, if you wanted to assign different types based on a condition, you often had to explicitly cast them to a common base type (like object). Target-typed conditional expressions remove this necessity. The second example infers the type to object to accommodate both string and int. If a common type doesn't exist, you must explicitly cast one of the options. For example, you couldn't target a 'string' variable and have '123' be an option unless you cast it string before.

bool isEnabled = true;

// Before C# 9.0 (explicit cast required)
object objBefore = isEnabled ? (object)"Enabled" : (object)123;

// C# 9.0 and later (target-typed)
object objAfter = isEnabled ? "Enabled" : 123;

Console.WriteLine(objBefore.GetType()); // Output: System.String
Console.WriteLine(objAfter.GetType());  // Output: System.Object

Concepts Behind the Snippet

The core concept is type inference. The C# compiler analyzes the context (the variable being assigned to) to determine the appropriate type for the conditional expression. This reduces verbosity and makes the code easier to understand. This works only if all branches of the conditional operator can be implicitly converted to the target type. If there are user defined implicit cast operator, the operator will be used to convert the branch to the target type.

Real-Life Use Case

Consider a scenario where you need to create a logger instance based on a configuration setting. Using target-typed conditional expressions, you can simplify the logger creation:

This example demonstrates how target-typed conditionals can make factory methods cleaner and more readable, reducing boilerplate code.

public interface ILogger
{
    void Log(string message);
}

public class ConsoleLogger : ILogger
{
    public void Log(string message) => Console.WriteLine($"Console: {message}");
}

public class FileLogger : ILogger
{
    private readonly string _filePath;

    public FileLogger(string filePath)
    {
        _filePath = filePath;
    }

    public void Log(string message) => File.AppendAllText(_filePath, message + Environment.NewLine);
}

public class LoggerFactory
{
    public static ILogger GetLogger(bool logToFile, string filePath = "log.txt")
    {
        // Target-typed conditional expression
        return logToFile ? new FileLogger(filePath) : new ConsoleLogger();
    }
}

Best Practices

  • Keep it simple: Use target-typed conditional expressions when the intent is clear and the type inference doesn't introduce ambiguity.
  • Ensure Type Compatibility: Make sure the types of the conditional expression's branches are compatible with the target type, or that an implicit conversion exists.
  • Avoid Nested Conditionals: Deeply nested conditionals can decrease readability. Refactor complex logic into separate methods if necessary.

Interview Tip

Be prepared to explain the benefits of target-typed conditional expressions (reduced verbosity, improved readability) and their limitations (type compatibility requirements). Also, understand how they differ from traditional conditional expressions.

When to Use Them

Use target-typed conditional expressions when:

  • You're assigning the result of a conditional expression to a variable or property.
  • The compiler can easily infer the target type from the context.
  • You want to reduce redundant type specifications.

Alternatives

Alternatives to target-typed conditional expressions include:

  • Traditional Conditional Expressions: Explicitly casting each branch to the target type.
  • If-Else Statements: Using a standard if-else block for more complex logic.
  • Factory Pattern: Encapsulating object creation logic in a separate class or method (as shown in the Real-Life Use Case).

Pros

  • Reduced Verbosity: Less code to write and maintain.
  • Improved Readability: Cleaner and more concise expressions.
  • Simplified Syntax: Easier to understand and use.

Cons

  • Type Inference Issues: If the target type cannot be clearly inferred, the compiler will throw an error.
  • Potential for Confusion: Overuse in complex scenarios can reduce readability if the type inference becomes non-obvious.

FAQ

  • What version of C# introduced target-typed conditional expressions?

    Target-typed conditional expressions were introduced in C# 9.0.

  • Can I use target-typed conditional expressions with any type?

    Yes, you can use them with any type as long as the compiler can infer the target type and the types of the conditional expression's branches are compatible with the target type or an implicit conversion exists.

  • What happens if the compiler cannot infer the target type?

    If the compiler cannot infer the target type, it will generate a compilation error, indicating that it cannot determine the type of the conditional expression.