将主构造函数参数传递给基类时如何“正确”(惯用)避免 CS9107

ang*_*son 21 .net c# c#-12.0

在 C# 12 中,我们获得了普通类的主构造函数。

考虑以下代码:

new Derived("XXX").Test();

public class Base(string name)
{
    protected void Log() => Console.WriteLine("Base: " + name);
}

public class Derived(string name) : Base(name)
{
    public void Test()
    {
        base.Log();
        Console.WriteLine("Derived: " + name);
    }
}
Run Code Online (Sandbox Code Playgroud)

string name这会对主构造函数的参数发出以下警告Derived

Program.cs(8,42):警告 CS9107:参数“字符串名称”被捕获到封闭类型的状态中,并且其值也传递给基本构造函数。该值也可能由基类捕获。

我怎样才能避免这个警告,我应该使用编译指示来消除它吗?或者有更好的方法来避免吗?是不是代码写错了?我不确定我是否能看到替代方案,除了放弃主要构造函数并将整个内容重写为:

new Derived("XXX").Test();

public class Base
{
    protected readonly string _name;

    protected Base(string name)
    {
        _name = name;
    }

    protected void Log() => Console.WriteLine("Base: " + _name);
}


public class Derived : Base
{
    public Derived(string name) : base(name) { }

    public void Test()
    {
        base.Log();
        Console.WriteLine("Derived: " + base._name);
    }
}
Run Code Online (Sandbox Code Playgroud)

请指教。


注意:这是一个人为的示例,使用 Microsoft.Extensions.Configuration 中的配置对象从更复杂的类层次结构简化而来,其中多个级别的类都需要访问配置。

shi*_*ngo 7

是不是代码写错了?

是的,这是错误的。

string name在主构造函数中只是一个参数,但是当您在封闭类型中使用它时,编译器会自动将其转换为私有字段,因此您在类中创建了一个附加私有字段Derived,而实际上name在语句中Console.WriteLine("Derived: " + name);并没有引用基类中的字段。(换句话说,如果你有一个nameBase类中发生变化的方法,Derived.Test则不会改变)

为了避免编译器自动生成意外的字段,您需要照常将参数分配给字段或属性,并且不要在派生类中使用此参数。

  • _“要纠正这个问题,您需要像往常一样将参数分配给字段或属性,而不是使用该参数来避免编译器自动生成字段”_ - 我觉得必须这样做就违背了主要因素的要点旨在产生更简洁的代码 - 唉 - 前进 1 步,后退 2 步。 (7认同)
  • @Dai我想这是我真正的问题,似乎为了摆脱类层次结构中引入的警告,在使用主构造函数时,要么不使用主构造函数,要么添加我感觉目的的额外代码主要构造函数是要摆脱的。我将在基类中引入一个受保护的字段并使用它。 (3认同)

Mag*_*nus 6

也许使用财产?无论如何,您可能希望将您的字段保密。

public class Base(string name)
{
    protected string Name => name;
    protected void Log() => Console.WriteLine("Base: " + Name);
}

public class Derived(string name) : Base(name)
{
    public void Test()
    {
        base.Log(); 
        Console.WriteLine("Derived: " + Name);
    }
}
Run Code Online (Sandbox Code Playgroud)