C#
CS9107
constructor parameters
base class
programming tips

How to properly idiomatic avoid CS9107 when passing primary constructor parameters to base

Master System Design with Codemia

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

Introduction

CS9107 appears when a primary constructor parameter is passed to a base constructor and also captured by the derived type. The warning is not about syntax alone; it is about duplicated state and unclear ownership. The idiomatic fix is usually to decide which class should store the value and then use that one source of truth.

What Triggers CS9107

This pattern causes the warning:

csharp
1public class Base(string name)
2{
3    protected string Name => name;
4}
5
6public class Derived(string name) : Base(name)
7{
8    public void Print() => Console.WriteLine(name);
9}

The same name value is used twice:

  • passed into the base constructor
  • captured again by the derived class because Print references it

The compiler warns because both types may end up retaining the same value, which is often redundant.

Preferred Fix: Let the Base Own the Value

If the value is part of the base class contract, store it in the base and read it from there.

csharp
1public class Base(string name)
2{
3    protected string Name { get; } = name;
4}
5
6public class Derived(string name) : Base(name)
7{
8    public void Print() => Console.WriteLine(Name);
9}

This is the most idiomatic solution in typical inheritance hierarchies. The base receives the constructor parameter, stores it once, and the derived type consumes the inherited member.

Another Fix: Stop Capturing It in the Derived Type

Sometimes the derived type does not need the parameter directly at all. In that case, do not reference the primary constructor parameter from the body.

csharp
1public abstract class HandlerBase(ILogger logger)
2{
3    protected ILogger Logger { get; } = logger;
4}
5
6public sealed class UserHandler(ILogger logger) : HandlerBase(logger)
7{
8    public void Run()
9    {
10        Logger.LogInformation("Running");
11    }
12}

Here, UserHandler no longer captures logger. The base owns it, which removes the warning and improves clarity.

When Duplicate Storage Is Intentional

Occasionally, both classes need related but distinct versions of the same constructor input. That should be explicit, not accidental.

csharp
1public class Base(string connectionString)
2{
3    protected string NormalizedConnectionString { get; } =
4        connectionString.Trim();
5}
6
7public class Derived(string connectionString) : Base(connectionString)
8{
9    private string OriginalConnectionString { get; } = connectionString;
10
11    public void Dump()
12    {
13        Console.WriteLine(OriginalConnectionString);
14        Console.WriteLine(NormalizedConnectionString);
15    }
16}

This still stores two values, but now the duplication is purposeful. One member holds the original input and the other holds the normalized form. The names make the design intent obvious.

Dependency Injection Case

CS9107 shows up often with dependency injection because service parameters are easy to pass to a base class and then accidentally reuse in the derived class.

Warning-prone version:

csharp
1public abstract class RepositoryBase(IDbConnection connection)
2{
3    protected IDbConnection Connection { get; } = connection;
4}
5
6public sealed class UserRepository(IDbConnection connection)
7    : RepositoryBase(connection)
8{
9    public IDbConnection GetConnection() => connection;
10}

Better version:

csharp
1public abstract class RepositoryBase(IDbConnection connection)
2{
3    protected IDbConnection Connection { get; } = connection;
4}
5
6public sealed class UserRepository(IDbConnection connection)
7    : RepositoryBase(connection)
8{
9    public IDbConnection GetConnection() => Connection;
10}

The fix is usually small, but it improves the ownership model a lot.

Design Rule of Thumb

When CS9107 appears, ask one question first: which type should conceptually own this value?

Use this rule:

  • if the value defines shared base behavior, store it in the base
  • if only the derived class needs it, do not pass it through the base unless required
  • if both need separate representations, name those representations explicitly

That approach leads to cleaner inheritance and makes the warning useful instead of annoying.

Common Pitfalls

  • Trying to silence CS9107 without clarifying which class actually owns the state.
  • Keeping both the primary constructor parameter and a semantically identical base property.
  • Duplicating injected services across base and derived classes for no benefit.
  • Hiding the base member with another field or property that means the same thing.
  • Treating the warning as harmless even when it points to muddled class design.

Summary

  • CS9107 happens when a primary constructor parameter is captured in the derived type and passed to the base.
  • The idiomatic fix is usually to let the base store the value once and use the base member.
  • If duplicate storage is intentional, make the distinction explicit in member names.
  • The warning is mainly about state ownership and inheritance clarity.
  • Clean design usually removes the warning naturally without hacks.

Course illustration
Course illustration

All Rights Reserved.