C#
lists
auto-initialization
programming
.NET

Auto-initializing C lists

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In C#, list initialization can mean several different things: creating an empty list, creating and populating it inline, or ensuring a property never stays null. The language offers several concise patterns, but they are not interchangeable. The best choice depends on whether you want mutability, predictable defaults, or compact object construction.

Basic Empty List Initialization

The simplest form creates an empty List<T> ready for later use.

csharp
1using System.Collections.Generic;
2
3List<int> numbers = new List<int>();
4numbers.Add(10);
5numbers.Add(20);

This is still the clearest option when items will be added over time and the initialization itself is not the point of the code.

Collection Initializers for Preloaded Data

If you already know the initial contents, collection initializers are concise and readable.

csharp
1using System;
2using System.Collections.Generic;
3
4var names = new List<string> { "Alice", "Bob", "Carla" };
5Console.WriteLine(string.Join(",", names));

Under the hood, this is just repeated Add calls, but the syntax is more expressive when declaring sample data, defaults, or configuration.

Auto-Initialize List Properties

Many developers use “auto-initializing” to mean a property should never be null. A property initializer is a strong default for this.

csharp
1using System.Collections.Generic;
2
3public class Order
4{
5    public List<string> Tags { get; set; } = new List<string>();
6}

This avoids repetitive null checks and makes object usage safer. It is especially useful for DTOs, form models, and aggregate roots that expose collection properties.

It also makes serialization and binding code more predictable because consumers can assume the collection exists, even when it is empty.

Target-Typed new in Modern C#

If your language version supports it, target-typed new reduces repetition.

csharp
1using System.Collections.Generic;
2
3List<int> values = new();
4List<string> labels = new() { "A", "B", "C" };

This is purely syntactic sugar, but many teams prefer it for local variable declarations where the type is already obvious.

Initialize in Object Construction

Collection properties can be populated directly inside object initializers.

csharp
1using System.Collections.Generic;
2
3public class Report
4{
5    public List<string> Columns { get; set; } = new();
6}
7
8var report = new Report
9{
10    Columns = new List<string> { "Name", "City", "Score" }
11};

This is useful when the list contents are part of constructing a complete object graph up front.

Avoid null Collections in Public APIs

Returning null for a collection usually forces every caller to add defensive checks. Returning an empty list is often a cleaner contract.

csharp
1using System.Collections.Generic;
2
3public List<int> GetIds()
4{
5    return new List<int>();
6}

This pattern simplifies consumer code because foreach, Count, and LINQ operations remain safe without extra guards.

Capacity-Aware Initialization

If you know approximately how many elements will be inserted, initialize capacity to reduce resizing overhead.

csharp
using System.Collections.Generic;

var measurements = new List<double>(capacity: 10_000);

This does not change semantics, but it can reduce allocations in performance-sensitive code paths.

Consider Immutability When Appropriate

Sometimes the best initialization pattern is not a mutable list at all. If the collection should not change after construction, a read-only or immutable representation may be better.

csharp
using System.Collections.Generic;

IReadOnlyList<string> roles = new List<string> { "Admin", "Editor" };

The important part is matching the collection type to the ownership model, not defaulting to List<T> for every case.

Initialization style is really part of the object contract. If callers should add items freely, a mutable list is fine. If they should only read values, the type should communicate that.

Common Pitfalls

  • Leaving list properties uninitialized and then hitting NullReferenceException.
  • Using collection initializers when the list is meant to stay immutable.
  • Returning null instead of an empty collection from APIs.
  • Forgetting capacity for large append-heavy workloads.
  • Replacing clear explicit initialization with shorter syntax that makes type intent less obvious.

Summary

  • Empty lists, collection initializers, and property initializers solve different problems.
  • Property-level auto-initialization is a good default for collection properties that should never be null.
  • Collection initializers are best when the initial contents are known at construction time.
  • Target-typed new improves brevity but does not change behavior.
  • Use capacity-aware initialization and stronger collection interfaces when the workload or API contract justifies it.

Course illustration
Course illustration

All Rights Reserved.