Calling virtual method from base class ctor #6136
Replies: 5 comments 18 replies
-
This has been a known aspect of the design of the runtime since 1.0. It's discouraged to call a virtual method from the constructor. What do you suggest that |
Beta Was this translation helpful? Give feedback.
-
Nullable constructor analysis doesn't stop you from accessing any members, virtual or non-virtual, before all the fields are in the expected state (i.e. construction is "complete".) There is an official analyzer to warn users away from accessing virtual members from constructors. https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2214 |
Beta Was this translation helpful? Give feedback.
-
This might be solved if the "validator"-method would ever be added. |
Beta Was this translation helpful? Give feedback.
-
Have you ever thought about a replacement of the |
Beta Was this translation helpful? Give feedback.
-
class Base
{
public Base()
{
this.Foo();
}
protected virtual void Foo() { }
}
class Child : Base
{
string _str = "abc"; // Field initializers are executed before the base constructor
protected override void Foo()
{
Console.Write(this._str.Length);
}
} |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
This is a known quirk of C#:
This causes an NRE, despite compiling without any NRT warnings. I'm not sure if it's too late to fix now, but wanted to discuss anyway. Below is a possible solution to the problem.
In my proposal, another constructor is emitted, which is unspeakable, and accepts a new parameter of an enum type: option 1 - execute the "pre" code; option 2 - execute the "post" code; option 3 - execute both "pre" and "post" code.
If this parameter is option 1 or 3, the ctor code from beginning to that new pseudo-label is executed.
Then, if this parameter is option 2 or 3, the ctor code from the new pseudo-label to the end is executed.
The actual ctor just calls the unspeakable ctor with "full" option.
Child
ctor: 1) callsBase
unspeakable ctor with "pre" option, 2) executes its own body, 3) callsBase
unspeakable ctor with "post" option.Basically, the above compiles to:
WRONG SOLUTION
In my proposal, the actual `Base` ctor consists of the code from beginning to that new pseudo-label. (Syntax is up for discussion.) Another method is also output, which consists of the code from the new pseudo-label to the end. `Child` ctor: 1) calls `Base` ctor, 2) executes its own body, 3) calls said `Base` "post-ctor" method. Basically, the above compiles to:
Beta Was this translation helpful? Give feedback.
All reactions