C# tutorials > Modern C# Features > C# 6.0 and Later > How has target typing improved in recent C# versions?

How has target typing improved in recent C# versions?

Target typing in C# simplifies code by allowing the compiler to infer the type of an expression from the context in which it's used. This reduces redundancy and improves readability. This tutorial explores how target typing has evolved in recent C# versions, specifically focusing on its improvements and applications.

Introduction to Target Typing

Target typing allows the compiler to infer the type of an expression from its surrounding context. Instead of explicitly specifying the type on the right-hand side of an assignment, the compiler can determine it based on the variable being assigned to. This reduces boilerplate code and makes your code cleaner.

Simple Target Typing Example (C# 9.0 and later)

C# 9.0 introduced significant improvements to target typing with the introduction of target-typed new expressions. The new() syntax allows you to omit the type name when creating new objects, as long as the target type is clear from the context. In the first example, the compiler knows that new() should create a List because it's being assigned to a variable of that type.

The second example shows the usage with object initializers. The compiler deduces the type of the person variable as Person.

The third example shows the usage as a return value of a function

List<string> names = new(); // Target-typed new expression

var person = new Person { Name = "Alice", Age = 30 }; //Target-typed new expression with object initializer

return new() { X = 1, Y = 2 }; // Target-typed new expression for return value

Target Typing with Conditional Expressions

Target typing also works well with conditional (ternary) operators. The compiler can infer the type of the expression based on the target type. In this sample, the null! is used to tell the compiler to ignore the null possibility.

string message = (isAdult ? "Welcome" : null)!;

Concepts behind the snippet

The key concept behind target typing is compiler inference. The compiler analyzes the context of an expression to determine its type. This reduces the need for explicit type declarations, making code more concise and readable.

Real-Life Use Case Section

Consider a scenario where you're creating a complex object like an Order with nested OrderItems. Target typing can significantly simplify the creation process, especially when combined with object initializers.

The CreateNewOrder method demonstrates this. The new() syntax is used to create both the Order and the List, making the code cleaner and more readable.

public class Order
{
    public int OrderId { get; set; }
    public DateTime OrderDate { get; set; }
    public List<OrderItem> Items { get; set; }
}

public class OrderItem
{
    public int ProductId { get; set; }
    public int Quantity { get; set; }
}

public Order CreateNewOrder()
{
    return new() // Target-typed new expression
    {
        OrderId = 123,
        OrderDate = DateTime.Now,
        Items = new() // Target-typed new expression
        {
            new OrderItem { ProductId = 1, Quantity = 2 },
            new OrderItem { ProductId = 2, Quantity = 1 }
        }
    };
}

Best Practices

  • Use Target Typing When Appropriate: Target typing is most effective when the target type is clear from the context. Avoid using it in situations where it might make the code less readable.
  • Maintain Clarity: While target typing reduces boilerplate, prioritize code clarity. If omitting the type makes the code harder to understand, it's better to explicitly specify the type.
  • Consider Code Reviews: Ensure that code reviews focus on the readability of code that uses target typing to prevent potential misunderstandings.

Interview Tip

When discussing target typing in interviews, be prepared to explain its benefits, how it works, and when it's appropriate to use it. Also, be ready to discuss potential drawbacks, such as reduced code clarity in certain situations. Give the interviewer examples to show that you have the proper understanding.

When to use them

Use target typing when:

  • The target type is immediately obvious from the assignment context.
  • You want to reduce verbosity and improve code readability.
  • You're working with object initializers and complex object constructions.

Memory footprint

Target typing itself does not directly affect the memory footprint of your application. It's a compile-time feature that helps the compiler infer types, but the underlying object creation and memory allocation remain the same as if you had explicitly specified the type.

Alternatives

Before target typing, you would have to explicitly specify the type on both sides of an assignment. The main alternative is simply to write out the full type name. This is more verbose but can sometimes improve readability.

Pros

  • Improved Readability: Reduces boilerplate code, making code cleaner and easier to read.
  • Reduced Verbosity: Less typing required, especially when dealing with complex types.
  • Conciseness: Results in more compact and expressive code.

Cons

  • Potential for Reduced Clarity: If the target type isn't immediately obvious, it can make the code harder to understand.
  • Dependency on Compiler Inference: Relies on the compiler's ability to correctly infer the type, which might not always be straightforward.

FAQ

  • Does target typing affect runtime performance?

    No, target typing is a compile-time feature and does not impact runtime performance. The compiled code is the same regardless of whether you use target typing or explicitly specify the type.
  • Can I use target typing with all types?

    Target typing works best when the target type is clear and unambiguous. It's most commonly used with object creation, assignment, and method return types. However, it might not be suitable in all scenarios.
  • Is target typing available in all C# versions?

    Target-typed new expressions (using new()) were introduced in C# 9.0. Basic target typing concepts existed in earlier versions, but C# 9.0 significantly improved its capabilities.