Virtual call of the participant in the constructor - why is one okay and the other not?

Using the code below, Resharper raises the warning "virtual member call in constructor":

public class UserDetailViewModel : Screen { public UserDetailViewModel() { // DisplayName is a virtual member of Screen DisplayName = "User Details"; } } 

If I change the code like this, the warning disappears:

 public class UserDetailViewModel : Screen { public UserDetailViewModel() { SetName(); } private void SetName() { DisplayName = "User Details"; } } 

Why is there a warning, but not another? Is the second way somehow correct, or is it just beyond what ReSharper can detect as potentially dangerous?

+7
source share
3 answers

This is just a limitation of ReSharper. He uses a bunch of heuristics to find code he can warn about, but he won't find everything. To do this, you need to solve the stop problem. This is not feasible.

The lesson here is pretty simple:
the absence of a warning does not mean that there is nothing to warn about.

+13
source

In Caliburn.Micro, it is usually set to DisplayName, overriding the OnInitialize () method, for example.

  protected override void OnInitialize() { DisplayName = "User Details"; base.OnInitialize(); } 

OnInitialize () is called only once, and you no longer trigger a warning in Resharper. See also here .

+3
source

A warning is given because of a problem that may occur in the following situation.

  • An object of a derived type UserDetailViewModel , say, "ConcreteModel" is being built

  • ConcreteModel overrides the Screen.DisplayName property. In a property set method, it depends on the constructed completed ConcreteModel , say, accessing another member that is initialized in the constructor.

In this case, the above code throws an exception.

The correct way to solve this is to declare DisplayName sealed in the UserDetailViewModel . Now you can be sure that it is normal to ignore the warning.

The following example demonstrates this. Uncommenting strings in Der causes a compilation error.

 class Base { public virtual string DisplayName { get; set; } } class Der : Base { public Der() { // ok to ignore virtual member access here DisplayName = "Der"; } public override sealed string DisplayName { get; set; } } class Leaf : Der { private string _displayName; public Leaf() { _displayName = "default"; } //override public string DisplayName //{ // get { return _displayName; } // set { if (!_displayName.Equals(value)) _displayName = value; } //} } 
+1
source

All Articles