Invoke a virtual member in the constructor when assigning a value to a property

I have an Abstract class and Derived class. An abstract class defines an abstract property called Message. In a derived class, a property is implemented by overriding the abstract property. The constructor of the derived class takes a string argument and assigns it to the Message property. In Resharper, this assignment leads to the warning "Virtual call of the participant in the constructor".

AbstractClass has this definition:

public abstract class AbstractClass { public abstract string Message { get; set; } protected AbstractClass() {} public abstract void PrintMessage(); } 

And DerivedClass is as follows:

 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); } } 

I found other questions about this warning, but in these situations there is an actual method call. For example, in this question , Matt Howels answer contains sample code. I will repeat this here for convenience.

 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 does not describe what error the warning should appear, but I assume that it will be when calling DoSomething in the Parent constructor. In this example, I understand what is meant by the name of the virtual principal. The participant is called in the base class in which only the virtual method exists.

In my situation, however, I do not understand why assigning the value Message will cause a virtual member. Both the invocation and implementation of the Message property are defined in a derived class.

Although I can get rid of the error by creating my Derived Class sealed , I would like to understand why this situation leads to a warning.

Update Based on Brett's answer, I did my best to create a ChildClass derived from DerivedClass, which would ultimately result in an exception. Here is what I came up with:

 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); } } } 

Of course, itโ€™s a little silly to use _foo in the Message setter, but the fact is that ReSharper does not see anything bad in this class.

If, however, you try to use ChildClass in such a program:

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

When you create a ChildClass object, you will get a NullReferenceException. The exception will be thrown by ChildClass trying to use _foo.ToUpper() , because _foo is not yet initialized.

+4
source share
1 answer

This is because the Message property can be overridden with the class ChildClass : DerivedClass - at this point you can call the code in the Message on the ChildClass from ctor to DerivedClass , and your ChildClass instance may not be fully initialized.

This is why the DerivedClass solution sealed the problem - it cannot be inherited.

+6
source

Source: https://habr.com/ru/post/1334657/


All Articles