This question already has answers here:
Virtual member call in a constructor
(18 answers)
Closed 6 years ago.
I have the issue where I need to call a virtual function in my abstract class' constructor.
internal abstract class Item
{
protected Item(...)
{
...
CreateBuyButton(...);
}
protected abstract void CreateBuyButton(...);
}
If I have my code like this resharper is notifying me about the problem however if I refactor the call into another method resharper doesn't seem to count this as a problem and I'm not sure if it is a problem or not.
internal abstract class Item
{
protected Item(...)
{
...
GetValue(...);
}
protected abstract void CreateBuyButton(...);
private void GetValue(...)
{
CreateBuyButton(...);
}
}
Is this valid ? Will the problem still persist ?
Yes, it could still be a problem
When the constructor for your base class runs, the constructor(s) for the derived classes haven't run yet. If the overridden method contains logic that depends on the derived class' state, it could encounter issues, because the state hasn't been initialized yet.
You can avoid the problem by removing the logic from the constructor and using lazy initialization instead, e.g.
abstract class Item
{
private Button _buyButton = null;
public Item()
{
//Do nothing
}
public Button BuyButton
{
get
{
if (_buyButton == null) CreateBuyButton(); //Lazy initialization
return _buyButton;
}
}
public abstract void CreateBuyButton();
}
If you need to pass some state, you'll have to store it:
abstract class Item
{
private string _productName;
private Button _buyButton = null;
public Item(string productName)
{
_productName = productName;
}
public Button BuyButton
{
get
{
if (_buyButton == null) CreateBuyButton(_productName); //Lazy initialization
return _buyButton;
}
}
public abstract void CreateBuyButton(string caption);
}
Related
This question already has answers here:
Calling this and base constructor?
(1 answer)
How do I call both this and base constructor
(2 answers)
Can I call both this and base overloads in a constructor?
(1 answer)
Closed 3 years ago.
I know how to call another constructor for a constructor from the same class or the base class, but how can I do both at once? Here is an example of what I am looking to achieve, noting that in a real case we might want to do something more complex than just set a property:
public class BaseClass
{
public BaseClass(object param)
{
// base constructor
}
}
public class DerivedClass
{
DateTime Date { get; private set; }
public DerivedClass()
{
Date = GenerateDate();
}
public DerivedClass(object param) : base(param)
{
// How do I make it call DerivedClass() ?
}
}
This code actually compiles in Sharp Lab. Not that I had to fix a few secondary things.
using System;
public class BaseClass
{
public BaseClass(object param)
{
// base constructor
}
}
public class DerivedClass : BaseClass
{
public DateTime Date { get; private set; }
public DerivedClass() : this(new object()) { }
public DerivedClass(object param) : base(param)
{
//Do Date = GenerateDate(); here
//Had to cut your pseudo code, as it broke compilation
}
}
You had it the wrong way around: You need DerivedClass() to call DerivedClass(object param). With multiple Constructors, the one you actually code out is always the one with the most arguments. All other Constructors are just there to chain towards it, giving a default value each step.
I am currently having some issues with accessing a private method from a overriden public method.
My situation is like this: I have a compiled .dll file which consist basically of this
public class OriginalHandler
{
public virtual void Request()
{
RedirectIfConditionIsFulfilled()
this.PeformRequest()
}
protected virtual bool PeformRequest()
{
}
private static void RedirectIfConditionIsFulfilled()
{
}
}
I need to alter the method PeformRequest(), So i make a public class, which inherit OriginalHandler and override the method as such:
public class ModifiedOriginalHandler : OriginalHandler
{
protected override bool PeformRequest()
{
}
}
To ensure that this method doesn't violate an "impact" scope, I have to ensure that it only get evaluated on certain sites,
We use this to ensure that HttpRequestProcess ONLY impact the desired site using this
namespace Sitecore.Sharedsource.Pipelines.HttpRequest
{
using System.Collections.Generic;
using Assert = Sitecore.Diagnostics.Assert;
using S = Sitecore;
public abstract class SiteSpecificHttpRequestProcessor: S.Pipelines.HttpRequest.HttpRequestProcessor
{
public abstract List<string> _sites;
public sealed override void Process(S.Pipelines.HttpRequest.HttpRequestArgs args)
{
Assert.ArgumentNotNull(args, "args");
if (S.Context.Site == null || !this._sites.FirstOrDefault(S.Context.Site.Name))
{
return;
}
this.DoProcess(args, this._sites.FirstOrDefault(S.Context.Site.Name));
}
protected abstract void DoProcess(S.Pipelines.HttpRequest.HttpRequestArgs args, string);
}
}
So include my ModifiedOriginalHandler to include this
public class SiteSpecificModifiedOriginalHandler: SiteSpecificHttpRequestProcessor
{
Public override List<String> _sites => new[]
{
"www.only.com" , "www.boat.com"
};
public virtual HttpContext GetHttpContext()
{
return HttpContext.Current;
}
public override void DoProcess(HttpRequestArgs args, string)
{
var mediaRequest = new ModifiedOriginalHandler ();
var context = GetHttpContext();
var site = Sitecore.Context.Site;
if (site == null)
{
return;
}
if (string != null)
{
mediaRequest.Request(context);
}
else
{
OriginalHandler baseClass = mediaRequest;
baseClass.Request(context);
}
}
}
This Is where I am having a problem, I can from the SiteSpecificModifiedOriginalHandler not call the protected method PeformRequest,
but can call the public method Request which internally calls the desired function, so I make an override function,
to ensure that the original is not being called but my modified version
public class ModifiedOriginalHandler : OriginalHandler
{
protected override bool PeformRequest()
{
}
public override void Request()
{
RedirectIfConditionIsFulfilled()
this.PeformRequest()
}
}
Which is where I am having my problem, RedirectIfConditionIsFulfilled is a private method,
and I can in no way make this method call as such. I could in my overridden function remove this call, but that would
require RedirectIfConditionIsFulfilled to be removed, which would alter the original functionality, which i don't want to do.
So how do i overcome this?
How do i access a private method in a overriden public method?
If you have access to OriginalHandler implementation then make the derived class a nested one:
class A {
private void Foo() { }
protected virtual void Bar() { }
public class B: A {
protected override void Bar() {
Foo(); \\ legal } } }
If you don’t then barring reflection there is no way to access from an external type a private member of another type.
You can't access a private method from an inherited class. (But you know that.)
But your question didn't give any reason why your method shouldn't be protected, which would expose it to inherited classes.
What you're describing is exactly why protected exists.
A nested class will work, but I don't recommend it unless you want every single inherited class that needs the private method to be nested inside the base class. What if some of those inherited classes have their own private methods and even more inherited classes need to access those? You'd have to nest classes inside your nested classes.
This question already has answers here:
Force base method call
(14 answers)
Closed 4 years ago.
I would like to override a method, but i still want the parent method to be called when i override. When i try to use :base() to call parent method, it says unexpected token.
public class A
{
public virtual void DoStuff()
{
//some code
}
}
public class B : A
{
public override void DoStuff() : base()
{
//some other code
}
}
In java i would be :
super.DoStuff()
You have the wrong syntax, you can call the base method using the base keyword anywhere in the body of the method. The :base() syntax is only for constructors.
public class A
{
public virtual void DoStuff()
{
//some code
}
}
public class B : A
{
public override void DoStuff()
{
base.DoStuff();
}
}
Can you add a Derived Class to a list of its base class then call a method of the Derived class from the list of base class(possibly by casting it back to the Derived class since you know it was originally a Derived class)
public class MySystem
{
public string name;
MySystem(string name)
{
this.name = name;
}
public void Update()
{
//dostuff
}
}
public class PowerSystem : MySystem
{
public int totalPower;
PowerSystem (string name, int power) : base(name)
{
this.totalPower = power;
}
public void Update()
{
base.Update();
//Do other stuff
}
}
void Main()
{
List<MySystem> SystemList = new List<MySystem>();
SystemList.Add(new System("Shields"));
SystemList.Add(new System("Hull"));
Power p = new Power("Power", 10);
SystemList.Add(p);
foreach(MainSystems ms in SystemList)
{
if(ms.name != "Power")
ms.Update();
else
(PowerSystem)ms.Update(); //This doesn't work
}
}
So what I'm trying to do is run the update method for every element in the list, with the exeption of the one I named power and instead run the Power.Update method.
The closest post I have found to answering this is here unfortunately I don't fully understand it.
I'm hoping that the list is holding a reference to PowerSystem p and that somehow I can convert it and access the PowerSystem menthod.
I hope this is clear.
Thanks
PS if you have a better idea for this I'm all ears.
Use polymorphism - mark Update in base class virtual and override it in derived class.
Base classes may define and implement virtual methods, and derived
classes can override them, which means they provide their own
definition and implementation. At run-time, when client code calls the
method, the CLR looks up the run-time type of the object, and invokes
that override of the virtual method. Thus in your source code you can
call a method on a base class, and cause a derived class's version of
the method to be executed.
public class MySystem
{
public string name;
MySystem(string name)
{
this.name = name;
}
public virtual void Update()
{
//dostuff
}
}
public class PowerSystem : MySystem
{
public int totalPower;
PowerSystem (string name, int power) : base(name)
{
this.totalPower = power;
}
public override void Update()
{
base.Update();
//Do other stuff
}
}
Now, PowerSystem.Update() will get called automatically
foreach(MainSystems ms in SystemList)
{
ms.Update();
}
For MySystem instances it will call MySystem.Update, but for PowerSystem instances the override will be called.
I would like to ask what are the risks of having something as follows:
abstract public class HtmlTemplateBuilder
{
HtmlSource source;
protected HtmlTemplateBuilder()
{
LoadTemplates();
}
public abstract void LoadTemplates();
}
The risk is if a derived class derives from the derived class:
DerivedClass2 -> #DerivedClass1 -> HtmlTemplateBuilder
This can be solved by sealing #DerviedClass1, but are there any more risks or better practices for implementing this functionality?
Thanks
The situation in which this pattern bit me is as follows: at some later stage you want to add a specialized HtmlTemplateBuilder, which can load different templates based on some criteria unknown to the class itself (maybe you decide you want some cool templates on a specific day of the year). That is:
public class SpecialHtmlTemplateBuilder : HtmlTemplateBuilder
{
private bool someCondition;
public override void LoadTemplates()
{
if (someCondition)
{
LoadTemplatesSet1();
}
else
{
LoadTemplatesSet2();
}
}
}
But how are you going to pass someCondition to the class? The following won't work:
public class SpecialHtmlTemplateBuilder : HtmlTemplateBuilder
{
private bool someCondition;
public SpecialHtmlTemplateBuilder (bool someCondition)
{
this.someCondition = someCondition;
}
// ...
}
because the assignment of this.someCondition will be done after calling the base constructor, i.e., after LoadTemplates() is called. Note that sealing derived classes does not solve this problem.
The way to solve this is as #Rahul Misra described: add an explicit Initialize method and call that after the constructor.
Have a look at this link which explains the perils with simple easy to understand examples
https://blogs.msmvps.com/peterritchie/2012/04/25/virtual-method-call-from-constructor-what-could-go-wrong/
I would remove the call to LoadTemplates from constructor and call Initialise on it when the templates actually need to be loaded and used.
abstract public class HtmlTemplateBuilder
{
HtmlSource source;
object locker = new object();
private bool initialised;
protected HtmlTemplateBuilder()
{
}
protected void Initialise()
{
lock (locker)
{
if(initialised)
{
LoadTemplates();
initialised = true;
}
}
}
public abstract void LoadTemplates();
}