gpt4 book ai didi

c# - 为属性赋值时在构造函数中调用虚拟成员

转载 作者:太空狗 更新时间:2023-10-30 00:57:40 24 4
gpt4 key购买 nike

我有一个抽象类和一个派生类。抽象类定义了一个名为 Message 的抽象属性。在派生类中,属性是通过覆盖抽象属性来实现的。派生类的构造函数采用字符串参数并将其分配给其 Message 属性。在 Resharper 中,此分配会导致警告“构造函数中的虚拟成员调用”。

AbstractClass 有这样的定义:

public abstract class AbstractClass {
public abstract string Message { get; set; }

protected AbstractClass() {}

public abstract void PrintMessage();
}

DerivedClass如下:

using System;

public class DerivedClass : AbstractClass {
private string _message;

public override string Message {
get { return _message; }
set { _message = value; }
}

public DerivedClass(string message) {
Message = message; // Warning: Virtual member call in a constructor
}

public DerivedClass() : this("Default DerivedClass message") {}

public override void PrintMessage() {
Console.WriteLine("DerivedClass PrintMessage(): " + Message);
}
}

我确实发现了一些关于此警告的其他问题,但在那些情况下,确实存在对方法的调用。例如,在 this question 中,Matt Howels 的回答包含一些示例代码。为了便于引用,我会在这里重复一遍。

class Parent {
public Parent() {
DoSomething();
}
protected virtual void DoSomething() {};
}

class Child : Parent {
private string foo;
public Child() { foo = "HELLO"; }
protected override void DoSomething() {
Console.WriteLine(foo.ToLower());
}
}

Matt 没有描述警告会出现什么错误,但我假设它会在调用 Parent 构造函数中的 DoSomething 时出现。在这个例子中,我理解了被调用的虚拟成员的含义。成员调用发生在基类中,基类中只存在一个虚方法。

然而,在我的情况下,我不明白为什么为 Message 赋值会调用虚拟成员。 Message 属性的调用和实现都在派生类中定义。

虽然我可以通过使我的派生类密封来消除错误,但我想了解为什么这种情况会导致警告。

更新根据 Brett 的回答,我尽力创建了一个派生自 DerivedClass 的 ChildClass,它最终会导致异常。这是我想出的:

using System;

public class ChildClass : DerivedClass {
private readonly string _foo;

public ChildClass() : base("Default ChildClass Message") {
_foo = "ChildClass foo";
}

public override string Message {
get { return base.Message; }
set {
base.Message = value;
Console.WriteLine(_foo.ToUpper() + " received " + value);
}
}
}

当然,在 Message setter 中使用 _foo 有点傻,但重点是 ReSharper 没有发现此类有任何问题。

但是,如果您尝试在这样的程序中使用 ChildClass:

internal class Program {
private static void Main() {
var childClass = new ChildClass();
childClass.PrintMessage();
}
}

创建 ChildClass 对象时,您将得到一个 NullReferenceException。 ChildClass 尝试使用 _foo.ToUpper() 时将引发异常,因为 _foo 尚未初始化。

最佳答案

这是因为您的 Message 属性可以被 class ChildClass : DerivedClass 覆盖 - 此时可以从 中的 ctor 调用 Message on ChildClass 中的代码DerivedClass,您的 ChildClass 实例可能未完全初始化。

这就是为什么让你的 DerivedClass 密封解决问题 - 它不能被继承。

关于c# - 为属性赋值时在构造函数中调用虚拟成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4625614/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com