【发布时间】:2011-01-07 12:50:04
【问题描述】:
我有一个抽象类和一个派生类。抽象类定义了一个名为 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 属性的调用和实现都在派生类中定义。
虽然我可以通过创建派生类sealed 来消除错误,但我想了解为什么这种情况会导致警告。
更新 根据 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 尚未初始化。
【问题讨论】:
标签: c# properties resharper virtual abstract-class