Accessing protected constructor from derived class instance - c#

G'day Folks,
I'm struggling with what I thought was a simple issue, but I've gone blind. Obviously, I'm doing something basic very wrong, but I can't see it.
What I'm trying to do: Create an instance of a base class from a derived class instance using a protected constructor.
What's happening: The protected constructor of the base class is inaccessible inside the derived class. Message: 'BaseClass.BaseClass(List)' is inaccessible due to its protection level
Consider the following code:
class BaseClass
{
protected readonly List<int> internalStuff;
// Normal constructor for everywhere else
public BaseClass()
{
internalStuff = new List<int>();
}
// this is the constructor I want to call; it shouldn't be accessible outside the derived classes hence protected
protected BaseClass( List<int> stuff )
{
internalStuff = new List<int>(stuff);
}
}
sealed class DerivedClass : BaseClass
{
public void ConvertToBaseClass( out BaseClass newBaseClassInstance )
{
newBaseClassInstance = new BaseClass(internalStuff);
}
}
The protected constructor should be visible to the derived class, right? Why is it inaccessible?
Edited to answer some questions. The code you see is the code that exists. I created the classes in a separate file and trimmed as much as sensible.
The reason I want to convert between the classes is the base class is "light" in that it contains no unmanaged code nor holds on resources. The derived class holds resources. When I am done with the derived class, but need to maintain the basic data, I want to convert to the base class.
Here is revised code to answer some of the comments below:
public class BaseClass
{
protected readonly List<int> internalStuff;
public BaseClass()
{
internalStuff = new List<int>();
}
protected BaseClass( List<int> stuff )
{
internalStuff = new List<int>(stuff);
}
}
sealed class DerivedClass : BaseClass
{
BaseClass bc;
public void ConvertToBaseClass( out BaseClass newBaseClassInstance )
{
bc = new BaseClass(internalStuff); // <- error
newBaseClassInstance = new BaseClass(internalStuff); // <- error
}
}
Public on BaseClass did nothing, nor did I expect it to. Both BaseClass and DerivedClass are in the same assembly and namespace so are visible to each other anyway.
Even if there is a BaseClass variable internal to derived class, it gives the same inaccessible error.
DerivedClass is a derived class, go figure. Why does it not have access?

There are two flaws to your request:
the instance of DerivedClass already IS and instance of the BaseClass so there is no need to convert it!
Your DerivedClass has not implemented the constructor overload with stuff parameter so there is no way for this class to access that constructor.
If the constructor is protected, then it can only be accessed via constructors in inherting classes or the base class itself, Normally we would use syntax like this when implementing a class and we want the specific base constructor to be called, but we only want internal logic to access it:
public sealed class DerivedClass : BaseClass
{
public DerivedClass ()
: base()
{
// the base implementation has been executed.
// now perform any other init logic you need.
}
private DerivedClass (List<int> stuff)
: base(stuff)
{
// the base implementation has been executed.
// now perform any other init logic you need.
}
// this is one way to access non-public constructors
public static DerivedClass CreateAnotherInstance(List<int> stuff)
{
return = new DerivedClass(stuff);
}
}
What you may not be aware of, and the reason that you don't need a Convert method at all is that and instance of DerivedClass IS an instance of BaseClass, the following statement is valid:
DerivedClass car = new DerivedClass();
BaseClass vehicle = car;
The following will also work if you are unsure if the base object was originally a specific derived implementation:
if (vehicle is DerivedClass derivedRef)
{
Console.Out.WriteLine("It was a DerivedClass instance all along");
}
else
{
Console.Out.WriteLine("Not a DerivedClass: " + vehicle.GetType().Name);
}
If your DerivedClass instance convert method returned a new instance of BaseClass then you would have to copy across all the neccessary properties and would lose the polymorphic abilities that Inheritance provides for our classes.
In regard to your update:
The reason I want to convert between the classes is the base class is "light" in that it contains no unmanaged code nor holds on resources. The derived class holds resources. When I am done with the derived class, but need to maintain the basic data, I want to convert to the base class.
I really can't understand why you would, that's not true, I understand your reasoning, I just don't think it is a good design, even to the point that i feel very strongly against providing an answer that will help you continue down this path... this type of pattern really doesn't need to use inheritance at all... with extreme caution, as in please do not do this:
public class BaseClass
{
protected readonly List<int> internalStuff;
public BaseClass()
{
internalStuff = new List<int>();
}
protected BaseClass(List<int> stuff)
{
internalStuff = new List<int>(stuff);
}
protected BaseClass CreateAsBase()
{
return new BaseClass(internalStuff);
}
// I see little point in allowing "stuff" to be passed through
// from the caller, this class already has access to the "stuff"
// but you've already demonstrated an unual taste for hard work
protected BaseClass CreateAsBase2(List<int> stuff)
{
return new BaseClass(stuff);
}
}
sealed class DerivedClass : BaseClass
{
public BaseClass ConvertToBaseClass()
{
return base.CreateAsBase();
...
// um, if you really need to, this is how you could pass the "stuff"
// I asusme you would only do this because you were going to modify
// it in a way that the base class could not anticipate.
return base.CreateAsBase2(aModifiedListOfInternalStuff);
}
}
Usually in cases like this, either there would be a Utility class or methods to handle the processing and intensive resource requirements, and you would pass around a reference to the DTO (Data Transfer Object) so you can discard the wrapper object, but the DTO would remain intact:
public class Vehicle
{
protected readonly List<int> internalStuff;
public Vehicle()
{
internalStuff = new List<int>();
}
protected Vehicle(List<int> stuff)
{
internalStuff = new List<int>(stuff);
}
public Color Color { get; set; }
}
public sealed class Car : Vehicle
{
public Car()
: base()
{
}
private Car(List<int> stuff)
: base(stuff)
{
}
public void AddOne()
{
internalStuff.Add(1);
}
}
// Wrapper that accepts a vehicle, and does "stuff" to it
public sealed class VehicleBusinessObjectWrapper : IDisposable
{
public Vehicle Vehicle { get; private set; }
public VehicleBusinessObjectWrapper(Vehicle dto)
{
Vehicle = dto;
}
public void ChangeColour(Color newColor)
{
Vehicle.Color = newColor;
/// you know, apply modifications to the Vehicle
}
public void Dispose()
{
// clean up your resources... if there are any
// for instance, deliberately clear the reference to the original DTO, just to prove a point
Vehicle = null;
// after this point, the Vehicle Object is still intact.
}
}
public static class BusinessLogic
{
public static void Test()
{
var originalCar = new Car();
using (var processor = new VehicleBusinessObjectWrapper(originalCar))
{
// We can still access the vehicle through the processor, we don't need inheritance
if (processor.Vehicle.Color != Color.Green)
processor.ChangeColour(Color.Green);
// do other stuff on the car, or on the vehicle...
if (processor.Vehicle is Car car)
{
car.AddOne();
}
}
// reference to wrapper is now gone, but our original car/vehicle still remains.
originalCar.ToString();
Vehicle v = originalCar;
Console.WriteLine(v == originalCar); // "True"
}
}

This is by design. protected members of the base class can only be accessed on a object reference of your own type. So new BaseClass(internalStuff) is invalid. But creating your own constructor that calls through to it would be valid:
DerivedClass(List<int> stuff) : base(stuff) {
Let's look at the specifications:
ECMA-335 specification, which defines the CLI on which C# is based, says as follows:
I.8.5.3.2 Accessibility of members and nested types
snip
family [this means protected in C#] – accessible to referents that support the same type (i.e., an exact type and all of the types that inherit from it). For verifiable code (see §I.8.8), there is an additional requirement that can require a runtime check: the reference shall be made through an item whose exact type supports the exact type of the referent. [my bold] That is, the item whose member is being accessed shall inherit from the type performing the access.
ECMA-334, which defines the C# language, says:
8.5.4 Protected access
When a protected instance member is accessed outside the program text of the class in which it is declared, and when a protected internal instance member is accessed outside the program text of the program in which it is declared, the access shall take place within a class declaration that derives from the class in which it is declared. Furthermore, the access is required to take place through an instance of that derived class type or a class type constructed from it. This restriction prevents one derived class from accessing protected members of other derived classes, even when the members are inherited from the same base class. [my bold]
So this restriction stops you from creating an instance of the base class, or indeed another derived class altogether, and calling protected base functions on it.
The constructor is no exception. You must have an instance of DerivedClass to call a protected BaseClass constructor, and you can obviously only do that if you are inside the constructor of DerivedClass.

You can call the base class contractor from the derived class's constructor.
Implementation:
public class A
{
protected List<int> MyList { get; }
public A()
{
MyList = new List<int>();
MyList.Add(1);
}
public int GetListCount()
{
return MyList.Count;
}
}
public sealed class B : A
{
public B() : base()
{
}
public A GetBase()
{
return (A)this;
}
}
Usage:
public class Program
{
public static void Main(string[] args)
{
B b = new B();
var a = b.GetBase();
Console.WriteLine(a.GetListCount());
}
}
This returns 1

... I am done with the derived class, but need to maintain the basic data ...
Well I wouldn't start from here... Instead of trying to solve this problem with inheritance, I would recommend solving it with composition.
Introduce a type to represent the structure of your basic data. Perhaps an interface to represent your basic functions (if any). Then your heavy resource classes can hold a reference to the basic data.
When you are done with the heavy class, you can keep a reference to the basic data and allow the heavy class to be garbage collected.

Related

Abstract method call in abstract class constructor with derived class context [duplicate]

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

How do I call a super class method from sub class object which has overridden?

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

Is it possible in C# for an object to pass a reference to itself to the constructor of a child object it creates in it's own base constructor?

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.

Using 'this' in base constructor?

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

Accessing subclass in base class... but different

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

Categories