I'm getting a warning from ReSharper about a call to a virtual member from my objects constructor.
Why would this be something not to do?
When an object written in C# is constructed, what happens is that the initializers run in order from the most derived class to the base class, and then constructors run in order from the base class to the most derived class (see Eric Lippert's blog for details as to why this is).
Also in .NET objects do not change type as they are constructed, but start out as the most derived type, with the method table being for the most derived type. This means that virtual method calls always run on the most derived type.
When you combine these two facts you are left with the problem that if you make a virtual method call in a constructor, and it is not the most derived type in its inheritance hierarchy, that it will be called on a class whose constructor has not been run, and therefore may not be in a suitable state to have that method called.
This problem is, of course, mitigated if you mark your class as sealed to ensure that it is the most derived type in the inheritance hierarchy - in which case it is perfectly safe to call the virtual method.
In order to answer your question, consider this question: what will the below code print out when the Child object is instantiated?
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()); //NullReferenceException!?!
}
}
The answer is that in fact a NullReferenceException will be thrown, because foo is null. An object's base constructor is called before its own constructor. By having a virtual call in an object's constructor you are introducing the possibility that inheriting objects will execute code before they have been fully initialized.
The rules of C# are very different from that of Java and C++.
When you are in the constructor for some object in C#, that object exists in a fully initialized (just not "constructed") form, as its fully derived type.
namespace Demo
{
class A
{
public A()
{
System.Console.WriteLine("This is a {0},", this.GetType());
}
}
class B : A
{
}
// . . .
B b = new B(); // Output: "This is a Demo.B"
}
This means that if you call a virtual function from the constructor of A, it will resolve to any override in B, if one is provided.
Even if you intentionally set up A and B like this, fully understanding the behavior of the system, you could be in for a shock later. Say you called virtual functions in B's constructor, "knowing" they would be handled by B or A as appropriate. Then time passes, and someone else decides they need to define C, and override some of the virtual functions there. All of a sudden B's constructor ends up calling code in C, which could lead to quite surprising behavior.
It is probably a good idea to avoid virtual functions in constructors anyway, since the rules are so different between C#, C++, and Java. Your programmers may not know what to expect!
Reasons of the warning are already described, but how would you fix the warning? You have to seal either class or virtual member.
class B
{
protected virtual void Foo() { }
}
class A : B
{
public A()
{
Foo(); // warning here
}
}
You can seal class A:
sealed class A : B
{
public A()
{
Foo(); // no warning
}
}
Or you can seal method Foo:
class A : B
{
public A()
{
Foo(); // no warning
}
protected sealed override void Foo()
{
base.Foo();
}
}
In C#, a base class' constructor runs before the derived class' constructor, so any instance fields that a derived class might use in the possibly-overridden virtual member are not initialized yet.
Do note that this is just a warning to make you pay attention and make sure it's all-right. There are actual use-cases for this scenario, you just have to document the behavior of the virtual member that it can not use any instance fields declared in a derived class below where the constructor calling it is.
There are well-written answers above for why you wouldn't want to do that. Here's a counter-example where perhaps you would want to do that (translated into C# from Practical Object-Oriented Design in Ruby by Sandi Metz, p. 126).
Note that GetDependency() isn't touching any instance variables. It would be static if static methods could be virtual.
(To be fair, there are probably smarter ways of doing this via dependency injection containers or object initializers...)
public class MyClass
{
private IDependency _myDependency;
public MyClass(IDependency someValue = null)
{
_myDependency = someValue ?? GetDependency();
}
// If this were static, it could not be overridden
// as static methods cannot be virtual in C#.
protected virtual IDependency GetDependency()
{
return new SomeDependency();
}
}
public class MySubClass : MyClass
{
protected override IDependency GetDependency()
{
return new SomeOtherDependency();
}
}
public interface IDependency { }
public class SomeDependency : IDependency { }
public class SomeOtherDependency : IDependency { }
Yes, it's generally bad to call virtual method in the constructor.
At this point, the objet may not be fully constructed yet, and the invariants expected by methods may not hold yet.
Because until the constructor has completed executing, the object is not fully instantiated. Any members referenced by the virtual function may not be initialised. In C++, when you are in a constructor, this only refers to the static type of the constructor you are in, and not the actual dynamic type of the object that is being created. This means that the virtual function call might not even go where you expect it to.
Your constructor may (later, in an extension of your software) be called from the constructor of a subclass that overrides the virtual method. Now not the subclass's implementation of the function, but the implementation of the base class will be called. So it doesn't really make sense to call a virtual function here.
However, if your design satisfies the Liskov Substitution principle, no harm will be done. Probably that's why it's tolerated - a warning, not an error.
One important aspect of this question which other answers have not yet addressed is that it is safe for a base-class to call virtual members from within its constructor if that is what the derived classes are expecting it to do. In such cases, the designer of the derived class is responsible for ensuring that any methods which are run before construction is complete will behave as sensibly as they can under the circumstances. For example, in C++/CLI, constructors are wrapped in code which will call Dispose on the partially-constructed object if construction fails. Calling Dispose in such cases is often necessary to prevent resource leaks, but Dispose methods must be prepared for the possibility that the object upon which they are run may not have been fully constructed.
One important missing bit is, what is the correct way to resolve this issue?
As Greg explained, the root problem here is that a base class constructor would invoke the virtual member before the derived class has been constructed.
The following code, taken from MSDN's constructor design guidelines, demonstrates this issue.
public class BadBaseClass
{
protected string state;
public BadBaseClass()
{
this.state = "BadBaseClass";
this.DisplayState();
}
public virtual void DisplayState()
{
}
}
public class DerivedFromBad : BadBaseClass
{
public DerivedFromBad()
{
this.state = "DerivedFromBad";
}
public override void DisplayState()
{
Console.WriteLine(this.state);
}
}
When a new instance of DerivedFromBad is created, the base class constructor calls to DisplayState and shows BadBaseClass because the field has not yet been update by the derived constructor.
public class Tester
{
public static void Main()
{
var bad = new DerivedFromBad();
}
}
An improved implementation removes the virtual method from the base class constructor, and uses an Initialize method. Creating a new instance of DerivedFromBetter displays the expected "DerivedFromBetter"
public class BetterBaseClass
{
protected string state;
public BetterBaseClass()
{
this.state = "BetterBaseClass";
this.Initialize();
}
public void Initialize()
{
this.DisplayState();
}
public virtual void DisplayState()
{
}
}
public class DerivedFromBetter : BetterBaseClass
{
public DerivedFromBetter()
{
this.state = "DerivedFromBetter";
}
public override void DisplayState()
{
Console.WriteLine(this.state);
}
}
The warning is a reminder that virtual members are likely to be overridden on derived class. In that case whatever the parent class did to a virtual member will be undone or changed by overriding child class. Look at the small example blow for clarity
The parent class below attempts to set value to a virtual member on its constructor. And this will trigger Re-sharper warning, let see on code:
public class Parent
{
public virtual object Obj{get;set;}
public Parent()
{
// Re-sharper warning: this is open to change from
// inheriting class overriding virtual member
this.Obj = new Object();
}
}
The child class here overrides the parent property. If this property was not marked virtual the compiler would warn that the property hides property on the parent class and suggest that you add 'new' keyword if it is intentional.
public class Child: Parent
{
public Child():base()
{
this.Obj = "Something";
}
public override object Obj{get;set;}
}
Finally the impact on use, the output of the example below abandons the initial value set by parent class constructor.
And this is what Re-sharper attempts to to warn you, values set on the Parent class constructor are open to be overwritten by the child class constructor which is called right after the parent class constructor.
public class Program
{
public static void Main()
{
var child = new Child();
// anything that is done on parent virtual member is destroyed
Console.WriteLine(child.Obj);
// Output: "Something"
}
}
Beware of blindly following Resharper's advice and making the class sealed!
If it's a model in EF Code First it will remove the virtual keyword and that would disable lazy loading of it's relationships.
public **virtual** User User{ get; set; }
There's a difference between C++ and C# in this specific case.
In C++ the object is not initialized and therefore it is unsafe to call a virutal function inside a constructor.
In C# when a class object is created all its members are zero initialized. It is possible to call a virtual function in the constructor but if you'll might access members that are still zero. If you don't need to access members it is quite safe to call a virtual function in C#.
Just to add my thoughts. If you always initialize the private field when define it, this problem should be avoid. At least below code works like a charm:
class Parent
{
public Parent()
{
DoSomething();
}
protected virtual void DoSomething()
{
}
}
class Child : Parent
{
private string foo = "HELLO";
public Child() { /*Originally foo initialized here. Removed.*/ }
protected override void DoSomething()
{
Console.WriteLine(foo.ToLower());
}
}
I think that ignoring the warning might be legitimate if you want to give the child class the ability to set or override a property that the parent constructor will use right away:
internal class Parent
{
public Parent()
{
Console.WriteLine("Parent ctor");
Console.WriteLine(Something);
}
protected virtual string Something { get; } = "Parent";
}
internal class Child : Parent
{
public Child()
{
Console.WriteLine("Child ctor");
Console.WriteLine(Something);
}
protected override string Something { get; } = "Child";
}
The risk here would be for the child class to set the property from its constructor in which case the change in the value would occur after the base class constructor has been called.
My use case is that I want the child class to provide a specific value or a utility class such as a converter and I don't want to have to call an initialization method on the base.
The output of the above when instantiating the child class is:
Parent ctor
Child
Child ctor
Child
I would just add an Initialize() method to the base class and then call that from derived constructors. That method will call any virtual/abstract methods/properties AFTER all of the constructors have been executed :)
Another interesting thing I found is that the ReSharper error can be 'satisfied' by doing something like below which is dumb to me. However, as mentioned by many earlier, it still is not a good idea to call virtual properties/methods in constructor.
public class ConfigManager
{
public virtual int MyPropOne { get; private set; }
public virtual string MyPropTwo { get; private set; }
public ConfigManager()
{
Setup();
}
private void Setup()
{
MyPropOne = 1;
MyPropTwo = "test";
}
}
I've been reading about Polymorphism and I've been through something interesting.
I have created two classes: a super class and a derived class. As you can see derived class inherits from the super class and using its method.
In the derived class I have overridden the method of super class.
So my question is: I want to call the super class method from an object of a derived class
For example:
derivedClass a = new derivedClass()
a.method();
I want a.methood() to execute the superclass method.
Is that possible?
Summing up your question: You have a base class and a derived class. The derived class overrides a virtual method of the base class. Given an instance of the derived class, is it possible to force a call to the base class version of the method, instead of the derived class?
Short answer: From inside the class, yes. From outside the class, no.
Essentially what you wish to do here is a non virtual call to a virtual method. It is legal to do a non-virtual call to a base class method, but only from inside the class:
class B
{
public virtual void M() { Console.WriteLine("B.M"); }
}
class D : B
{
public override void M() { Console.WriteLine("D.M"); }
public void BM() { base.M(); }
}
...
D d = new D();
d.M(); // D.M
d.BM(); // B.M
Now, for advanced players there are sneaky ways to call B.M with an instance of D as the receiver, and I'm not going to tell you what they are. You should not attempt to do so. The CLR may flag such attempts as violations of its "verified code" rules. The rules of virtual overriding are there for your convenience and safety. Do not attempt to do an end-run around those rules.
From outside the derived class it is not possible. From within the derived class it is.
If you have these classes defined:
class A
{
public virtual void Method1() { Console.WriteLine("A"); }
}
class B : A
{
override public void Method1() { Console.WriteLine("B"); }
public void BaseMethod1() { base.Method1(); }
}
You can execute the following:
B b = new B();
b.Method1(); //Outputs "B"
b.BaseMethod1(); //Outputs "A"
((A)b).Method1(); //***Outputs "B" (even though you cast it as A)
If you change overide to new then the output of the last line is "A"
You can try calling base method as per your requirement, if there is some condition, according to which you want to call it, you can use that condition as well.
public class SubClass : SuperClass
{
public bool IsCallBaseClassMethod { get; set; }
public override void Method(){
if (IsCallBaseClassMethod)
{
base.Method();
}
}
}
Set the condition according to your requirement for the object and call the method for same object.
SubClass testObject = new SubClass();
testObject.IsCallBaseClassMethod = true;
testObject.Method();
So, lets say I have the following objects:
public abstract class Chicken
{
public Egg Container { get; private set; }
protected Chicken(Egg container)
{
Container = container;
}
}
public abstract class Egg
{
public Chicken Contents { get; private set; }
protected Egg(Chicken contents)
{
Contents = contents;
}
}
public class Buckeye : Chicken
{
public Buckeye(Egg container) : base(container)
{
}
}
public class BrownEgg : Egg
{
public BrownEgg() : base(new Buckeye(this))
{
}
}
Thank you to Wikipedia for supplying the name of a chicken breed.
Anyway, the previous code won't compile. It will tell you "Cannot use 'this' in member initializer."
So, I want to know if there is a way this can be done. Can you pass a reference to the object being constructed, to a child object that is also being constructed, that needs to be passed to the outer objects base?
I probably worded the question title poorly, but it's a difficult concept to communicate succinctly.
You can't use this in call to base constructor (see Why can't you use 'this' in member initializers?).
You can pass creator function instead of populated object to let inner constructor to pass this. Something like:
protected Egg(Func<Egg, Chicken> contentsCreator)
{
Contents = contentsCreator(this);
}
public BrownEgg() : base(me => new Buckeye(me))
{
}
Nope, and here's why: the base constructor fires before your more derived constructor, but the base constructor would act upon this being your more derived class... Which isn't done being constructed because it's waiting for the base constructor to finish before firing your derived constructor. Not sure if that makes a lot of sense how I wrote it but basically you can't pass an unconstructed class to a base class.
I'm working on a project that involves a lot of interfacing and inheritance, which are starting to get a little tricky, and now I've run into a problem.
I have an abstract class State which takes in a Game object as a constructor argument. In my Game class's constructor, it takes in a State. The idea is that when inheriting from the abstract base Game class, when calling the base class's constructor, you give it an initial State object. However this State object takes in the same Game that you're creating it in. The code looks like this:
public class PushGame : ManiaGame
{
public PushGame() :
base(GamePlatform.Windows, new PlayState(this), 60)
{
}
}
However this doesn't work. I can only assume because the 'this' keyword is not usable until after the constructor has begun to execute. Trying to use it in your base class's constructor doesn't work, apparently. So what would be my best workaround for this? My plan B is to just remove the State argument from the Game class's constructor and just set the state inside the constructor code afterwards.
Is there an easier, less-intrusive way of doing this?
Clearly the ManiaGame class always uses objects of PlayState type, so you can move the creation at the ManiaGame level:
public class PushGame : ManiaGame
{
public PushGame() : base()
{
}
}
public class ManiaGame
{
PlayState ps;
public ManiaGame() {
ps = new PlayState(this);
}
}
If you want more concrete PlayState classes..
public class PushGame : ManiaGame
{
public PushGame() : base()
{
}
protected override PlayState CreatePlayState()
{
return new PushGamePlayState(this);
}
}
public class ManiaGame
{
PlayState ps;
public ManiaGame() {
ps = CreatePlayState();
}
protected virtual PlayState CreatePlayState()
{
return new PlayState(this);
}
}
public class PlayState
{
public PlayState(ManiaGame mg) {}
}
public class PushGamePlayState : PlayState
{
public PushGamePlayState(ManiaGame mg) : base(mg){}
}
If the State implementation used depends on the concrete Game class, then I would create a new instance of the State inside the constructor of the child Game class (PushGame) and access the State in the base class through the abstract property.
public class PushGame : ManiaGame
{
private readonly PlayState gamePlayState;
public PushGame() : base()
{
gamePlayState = new PlayState(this);
}
protected override State GamePlayState
{
get { return gamePlayState; }
}
}
public abstract class ManiaGame
{
protected abstract State GamePlayState { get; }
}
public class State
{
public State(ManiaGame mg) { }
}
public class PlayState : State
{
public PlayState(ManiaGame mg) : base(mg) { }
}
From the C# Language Specification
An instance constructor initializer cannot access the instance being created. Therefore it is a compile-time error to reference this in an argument expression of the constructor initializer, as is it a compile-time error for an argument expression to reference any instance member through a simple_name.
i.e. this can only be used to reference another constructor in the context of a constructor initializer, as the reference to the current object instance won't be available until the construction is completed.
i.e. this can be only used as a scoping keyword before the constructor executes:
: this("ParameterForAnotherConstructor")
But it is not available as a reference to the class instance, since it has not completed construction
: base(this) // Keyword this is not available in this context
And obviously we can't call any instance methods from the constructor initializer either
: base(GetThis()) // Object reference is required
To solve OP's problem, changes to the base Mania class seems inevitable, given the two-way coupling between PlayState and ManiaGame (or subclasses of ManiaGame, like PushGame). There are many patterns available to decouple tight dependencies like this, such as the Dependency Inversion Principal (i.e. abstract the coupling between the classes), or the Observer pattern - (one of the two classes raises events or allows callbacks to be hooked (e.g. delegates or Actions), allowing the second class to 'observe' state changes without the hard coupling between them.
There is a similar Stack Overflow question, Keyword 'this' (Me) is not available calling the base constructor with a workaround similar to your suggestion.
Does your design differentiate between a game (say backgammon) and a game in progress (a game of backgammon)? If you're trying to mix these two concepts then I would suggest modeling them separately. For example, Backgammon and BackgammonContest.
I've recenly experienced this issue when trying to pass concrete instances of implemented interfaces via this to the base constructor.
To work around it, I simply implemented an abstract method on the base class that fetched the instance I was looking for:
public abstract class BaseClass
{
...
protected abstract IMyInterface GetInterface();
...
}
public class DerivedClass : BaseClass, IMyInterface
{
...
protected override IMyInterface GetInterface()
{
return this;
}
...
}
In my base class code, you can then use GetInterface (or whatever type you need) to obtain the instance:
public abstract class BaseClass
{
public void Foo()
{
GetInterface().DoSomething();
}
}
I have a base class that has a subclass (could be a struct i suppose but not sure if it's appropriate) and a method.
class Base
{
protected class SubClass
{
public string word;
public int number;
}
protected void SomeMethod()
{
this.SubClass.word //this is where I'm struggling
}
}
Then i have a couple child classes that implement my baseClass, instantiate the Base.SubClass and add some values to the instantiated class.
class ChildClass1 : Base
{
public childSubClass = new SubClass();
public void DoSomethingRidiculous()
{
childSubClass.word = "WhoFarted";
}
}
class ChildClass2 : Base
{
public childSubClass = new SubClass();
public void DoSomethingRidiculous()
{
childSubClass.word = "ItStinks";
}
}
If possible, I would like to be able to get the value of SubClass.word from within the Base class. I think that my attempt at implementing my idea is probably wrong.
I'm not sure that you really need subclassing / class nesting. Just move out class SubClass declaration and declare protected field/property of SubClass type instead.
public class SubClass
{
public string word;
public int number;
}
public class Base
{
protected SubClass subClassInstance = new SubClass();
protected void SomeMethod()
{
this.subClassInstance.word //this is where I'm struggling
}
}
Then you can access subClassInstance inside both ChildClass1 and ChildClass2
The base class has no field or property of type SubClass, so you definitely cannot do what you propose directly.
One solution would be to add the field
public childSubClass = new SubClass();
to class Base itself. Is there a problem with this?
The other solution would be to use reflection to get the value of the field, assuming that the object you are reflecting on does have such a field. This is really far-fetched and while it might technically allow you to do what you propose, it has a very bad code smell.
I'm not sure why you're making a Sub Class instead of just making those two properties of the base class, but the reason you're having trouble with this line :
this.SubClass.word //this is where I'm struggling
is because you're not instantiating SubClass as a property of the base class.
A base class can not (or should not) access members of derived classes, and usually not even know about derived classes (some exceptions apply, such as in the case of the State Pattern). If the base should have access to a member, it should be declared in the base. If derived classes should also be able to use that member, then mark the member as protected.
class Base
{
protected Foo someFoo;
void Frob()
{
// can access methods/properties of someFoo instance
}
}
class Child
{
public Child()
{
someFoo = new Foo(); // child can also access someFoo
}
}