I have a base class that implements some logic and eventually calls an Action which was passed to the contructor.
public class BaseClass
{
private Action action;
public BaseClass(Action someAction)
{
action += someAction;
}
private void doStuff()
{
action();
}
}
Now I want to derive some child classes that implement some specific logic. In these child classes I have a method for that logic and my attempt was to pass this method to the base constructor. But this result in a compiler error CS0120: An object reference is required for the nonstatic field, method, or property 'member'.
public class SpecificClass : BaseClass
{
private int b;
public SpecificClass(int i)
: base(doSpecificStuff) // <-- compiler error CS0120 here
{
b = i;
}
private void doSpecificStuff()
{
// do something depending on b
}
}
I don't quite get why it fails at that point. Is it because the base constructor gets called first which means when calling it I do not have an instance of the child class (including the child's method)?
But why does the compiler asks for a reference to a nonstatic field? Actually I don't see anything static here. Is there a way to get a reference to doSpecificStuff at that point? this.doSpecificStuff does not work, resulting in CS0027: Keyword 'this' is not available in the current context.
Any suggestions for a better design?
This is exactly where object-oriented-design (OOP) and one of its principles, Polymorphism, comes in place, and what it was designed for.
By making doStuff virtual in the base class, we can override the method in the specific class and customize its behavior.
public class BaseClass
{
private Action? action;
public BaseClass(Action someAction)
{
action += someAction;
}
protected BaseClass()
{
}
protected virtual void doStuff()
{
action?.Invoke();
}
}
public class SpecificClass : BaseClass
{
private int b;
public SpecificClass(int i)
{
b = i;
}
protected override void doStuff()
{
// do something depending on b
}
}
I don't quite get why it fails at that point. Is it because the base constructor gets called first which means when calling it I do not have an instance of the child class (including the child's method)?
Sort of. There is actually an instance of the child class (the object is created immediately of the "right" type) but you can't refer to anything specific to the instance in the constructor initializer.
From section 15.11.2 of the draft C# 6 spec:
An instance constructor initializer cannot access the instance being created.
The best way of handling this really depends on the broader context. For example, you could accept a Func<BaseClass, Action> instead and cast:
public class BaseClass
{
private Action action;
public BaseClass(Func<BaseClass, Action> actionProvider)
{
action += actionProvider(this);
}
private void doStuff()
{
action();
}
}
... then:
public class SpecificClass : BaseClass
{
private int b;
public SpecificClass(int i)
: base(x => ((SpecificClass) x).doSpecificStuff)
{
b = i;
}
private void doSpecificStuff()
{
// do something depending on b
}
}
That's a bit tortuous though. If the action is always expected to be a method in the derived class, an option would be to create an abstract method in the base class and just override it in the derived class instead.
The error message means that the compiler is expecting this:
private static void doSpecificStuff()
{
// do something depending on b
}
Why? because when you call your action in doStuff, C# has no way to now that doSpecificStuff has to be called on the current (this) instance.
To compile, you would have to do something like this :
public class BaseClass
{
private Action action;
public BaseClass(Action<BaseClass> someAction)
{
action += () => someAction(this);
}
private void doStuff()
{
action();
}
}
public class SpecificClass : BaseClass
{
private int b;
public SpecificClass(int i): base(x => ((SpecificClass)x).doSpecificStuff()) // <-- compiler error CS0210 here
{
b = i;
}
private void doSpecificStuff()
{
// do something depending on b
}
}
I do not know exactly why you came up with this approach but why not just us inheritance? (Again, there might be some specific need I'm not aware of here, I'm just mentioning this for the record to post an answer as complete as possible) For instance:
public class BaseClass
{
public BaseClass()
{
}
protected virtual void doStuff()
{
// Doing stuff...
}
}
public class SpecificClass : BaseClass
{
private int b;
public SpecificClass(int i): base()
{
b = i;
}
protected override void doStuff()
{
// do something depending on b
base.doStuff()// if needed...
}
}
Related
I implemented the following structure:
public abstract class A
{
protected A()
{
Test();
}
private void Test()
{
Console.WriteLine("2");
}
}
public class B : A
{
public B() : base()
{
Console.WriteLine("1");
}
}
When I create an instance of class B, the method Test() is executed before the constructor calls in class B. In my case, this method should run after the child is fully initialized. A possible way to make it work would be to make Test() accessible from B and call it at the end of its constructor. That would work but if someone creates another subclass of A , there is a chance that he forgets to call the method. My question is whether there is a more general solution in the base class to make sure that the method is executed after a child is fully initialized.
The answer is no.
There is nothing built into .NET or C# that can make sure methods are being called after all descendant constructors have executed.
A different approach would be some form of the factory pattern, where your class would basically just provide you with another instance that has been correctly set up, and all required methods called.
That can't be done cause constructor initializer doesn't work that way. Rather you can choose to pass some parameter to base constructor, parameters which may be specific to your child class like
public abstract class A
{
protected A(string data)
{
Test(data);
}
private void Test(string data)
{
Console.WriteLine(data);
}
}
public class B : A
{
public B() : base("1")
{
//some other initialization logic here
}
}
You can't directly "insert" a method call before calling constructor of base class, because it's calling a method on an uninitialized object. But you can use the template method pattern:
abstract class A {
protected A () {
BeforeTest ();
Test ();
}
protected abstract void BeforeTest ();
private void Test () {
Console.WriteLine ("2");
}
}
class B : A {
protected override void BeforeTest () {
Console.WriteLine ("1");
}
}
internal class Program {
public static void Main (string [] args) {
new B ();
}
}
Alternatively, you can make Test method virtual:
abstract class A {
protected A () {
Test ();
}
protected virtual void Test () {
Console.WriteLine ("2");
}
}
class B : A {
protected override void Test () {
Console.WriteLine ("1");
base.Test ();
}
}
internal class Program {
public static void Main (string [] args) {
new B ();
}
}
Both examples outputs the same result:
1
2
With the abstract following class:
public abstract class A
{
public static string MyMethod()
{
return "a";
}
}
Why can't I built this derived abstract class:
public class B<T> where T : A
{
public void AnotherMethod()
{
var S1 = base.MyMethod(); // not allowed
var S2 = T.MyMethod(); // not allowed
}
}
I don't understand why since MyMethod will be available in type T.
There are two misconceptions in your question that collectively prevent both your attempts from working.
First your B class is not in any way derived from the A class, you have only said that it takes a generic parameter that must inherit from A.
Second as the user #recursive pointed out, static methods do not participate in inheritance so MyMethod would only ever be available as A.MyMethod()
You can make at least your first attempt work if you remove the static modifier and make B inherit from A instead of using generics.
// Removed the static modifier
public abstract class A
{
public string MyMethod()
{
return "a";
}
}
// Made B inherit directly from A
public class B : A
{
public void AnotherMethod()
{
var S1 = base.MyMethod(); //base technically isn't required
}
}
Aside from the fact that A.MyMethod is static, which clearly will not work since anything static does not take part in inheritance, even if you made it not static it still will not work. For example, this will not work either:
public abstract class A {
public string MyMethod() {
return "a";
}
}
public class B<T> where T : A {
public void AnotherMethod() {
var S1 = base.MyMethod(); // Line 1
var S2 = T.MyMethod(); // Line 2
}
}
Why?
You are saying where T : A which means that type T has to be a derived type from A. Your class B<T is not a derived type of A so Line 1 will not work.
But why is Line 2 not working?
T is a type and if T is inheriting A, then objects of type T will be able to do that. If you changed it like this, then it will work:
public abstract class A {
public string MyMethod() {
return "a";
}
}
public class B<T> where T : A {
public void AnotherMethod(T t) {
t.MyMethod();
}
}
public class C : A {
}
public class BClosed : B<C> {
public void Foo(C c) {
c.MyMethod();
this.AnotherMethod(c);
}
}
In the above code, C derives A which was your restriction. Then BClosed closes the generic type saying T is C so now you can call MyMethod of A and AnotherMethod of your generic.
Also, when you have a generic class you should use the generic type otherwise I do not see the use. So this is useless since it has no generic code:
public class B<T> where T : A {
public void AnotherMethod() {
}
}
I am programming a Programme for Vacations Control for Companies (only to learn, not serious). Now I have a Abstract Class called Employee. and 4 stages of Employees.
EveryOne has it own class:
NormalWorker
SubjectAreaLeader
ChefHumanResourceOfficer
CEO
The Normal Worker can ask for Vacations, the SAL can say ok or deny the Request. If he says ok it will go to the CHRO. He can veto it or pass it. The CEO is the last Instance who can veto it.
All classes inherits the Abstract Class. The Abstract Class has a delegate called
public delegate void applyVacations(Vacation what_vacations, bool pass_or_deny)
All Subclasses have a Method
void apply(Vacation what_vacation, bool pass_or_deny)
except of the NormalWorker. And the Constructors of the subclasses shall push this apply Method to the delegate.
passing the vacation request is final for all Instances.
Example:
namespace ex
{
public abstract class A
{
public delegate void foo();
public A()
{ }
}
class B : A
{
public B()
{
A.foo = childfoo; // Does not work
}
public void childfoo()
{/* Do something*/}
}
}
Greetings
You need to create a variable of type foo and then assign childfoo to it, like so:
private foo _handler;
public B()
{
// Assign our handler for the foo delegate.
_handler = childfoo;
// Now we can call it.
_handler();
}
foo is a delegate so it's a type
in B constructor you should write
foo handler = childfoo;
then you can call handler()
namespace ex
{
public abstract class A
{
public delegate void foo();
public A()
{ }
}
class B : A
{
private foo handler;
public B()
{
handler = childfoo;
}
public void callHandlerHere()
{
handler();
}
public void childfoo()
{/* Do something*/}
}
}
this is for exemple purpose of course
B b = new B();
b.callHandlerHere() // all object inheriting A can habe a callHandlerHere function for exemple
Even though all common sense says no, I still am asking this question just to get a second opinion and become sure.
If I have a class hierarchy like so:
public class IntermediateObjectContext : System.Data.Objects.ObjectContext
{
public static Action<string> PrintHello { get; set; }
}
public class MyDatabaseContext : IntermediateObjectContext
{
public ObjectSet<Foo> Foos
{
get { // ... }
}
}
Then from a third, unrelated to Entity Framework object, if I access the static member of the IntermediateObjectContext class, in this case, if I subscribe to the delegate of the class, will that somehow instantiate a new ObjectContext?
class SomeClass
{
public void SomeMethod()
{
IntermediateObjectContext.PrintHello += SayHello;
}
public void SayHello(string s)
{
Debug.Print(s);
}
}
All reason says no, common sense says it won't, but I just want to make sure. I am trying to track down a memory hogger object.
What happens if
What happens to the memory situation if I have a static collection for SomeClass types like so:
public class SomeClassCollection
{
private static Collection<SomeClass> _col =
new Collection<SomeClass>();
public void Add(SomeClass c) { _col.Add(c); }
public void Remove(SomeClass c) { _col.Remove(c); }
}
And then some code adds SomeClass instances to SomeClassCollection like so:
public SomeClassCollectionConfig
{
public static RegisterSomeClasses()
{
SomeClassCollection.Add(new SomeClass());
SomeClassCollection.Add(new DerivesClassOfSomeClass());
}
}
(1) No, it won't instantiate an object.
(2) What happens if:
There it will allocate the empty collection col the first time any member of SomeClassCollection is accessed.
From the code, that's all it will do. You aren't using _col anywhere in the code presented.
I have a C# class with a field that needs to be visible from outside the class, but should be changed only from within the class. However, the problem is that the field is updated via a public mutator method, not directly (or by a property):
public class FirstClass
{
public SecondClass TheField {get; private set;}
public FirstClass()
{
TheField = new SecondClass();
}
public void SomeMethod()
{
// ...
TheField.Update(/*parameters*/);
// ...
}
}
public class SecondClass
{
// some fields
public SecondClass() { }
public void Update(/*parameters*/)
{
// do something
}
}
In other words, I would like the method Update() to be accessible only from within FirstClass.
Few possible solutions and the reasons why I'm not safisfied with them:
Change SecondClass with a setter instead of a method. - Wouldn't work because I need to have parameters and a lot of stuff to do.
Make Update() internal instead of public. - Still accessible from within the assembly, not good enough.
Modify SecondClass from the FirstClass, ie. move the method Update() to FirstClass, make it private and expose all needed fields from SecondClass. - doesn't feel very object-oriented.
Call Update() from SecondClass constuctor(s) and make a new instance of SecondClass every time I need to update it. - The performance will suffer because there is some stuff in SecondClass that never changes and I would want to process it every time I call Update().
Is there a way to do this?
A basic implementation of #aquaraga's answer, but using interfaces instead:
public interface ISecond
{
// some properties
}
public class FirstClass
{
private readonly SecondClass _TheField;
public ISecond TheField { get { return _TheField; } }
public FirstClass()
{
_TheField = new SecondClass();
}
public void SomeMethod()
{
// ...
_TheField.Update(/*parameters*/);
// ...
}
private class SecondClass : ISecond
{
// some properties
public void Update(/*parameters*/)
{
// do something
}
}
}
Essentially, expose a public interface that has all the accessible members but no Update method. Employ a private nested class which has an Update method, but otherwise not accessible to calling code and expose it as the interface, not as the class.
Some sample usage:
FirstClass myFirst = ...
myFirst.SomeMethod(); //updates ok!
Console.WriteLine(myFirst.TheField.PropertyA); //can access properties of ISecond
myFirst.TheField.Update(); //compiler error!
One point is that you mention using "some fields"; as an interface you wouldn't be able to have fields but properties instead. I'm not sure if that's a deal breaker or not for you.
EDIT: You mentioned your intent to reuse the SecondClass and minimize code duplication. One quick fix might be to declare some abstract class, a protected Update method, employ an internal constructor (so other assemblies can't inherit from it), then expose the Update call with a minimal implementation:
public abstract class SecondClassBase : ISecond
{
// some properties
internal SecondClassBase()
{
}
protected void Update(/*parameters*/)
{
// do something
}
}
Then in your FirstClass, nothing changes except the nested class:
public class FirstClass
{
private readonly SecondClass _TheField;
public ISecond TheField { get { return _TheField; } }
public FirstClass()
{
_TheField = new SecondClass();
}
public void SomeMethod()
{
// ...
_TheField.Update(/*parameters*/);
// ...
}
private class SecondClass : SecondClassBase
{
public new void Update(/*parameters*/)
{
base.Update(/*parameters*/);
}
}
}
Still some code duplication, but all you need to do now is copy/paste the code; no need to redeclare the properties or the Update logic for each implementation of FirstClass. You could also rename the new Update method to something else to avoid method hiding, but I figured I'd keep the same calling signature you had before.
One way is to make a sub-class called UpdateableSecondClass an inner class to FirstClass.
It would inherit from SecondClass, and have a single method: Update()
Your SecondClass should not have the Update() method at all. You could continue exposing it to the rest of the world:
public SecondClass TheField {get; private set;}
I think that you can use this pattern:
public partial class FirstClass {
partial class ThirdClass: SecondClass {
public void PerformUpdate(/* parameters */) {
base.Update(/* parameters */);
}
}
public void SomeMethod() {
}
public FirstClass() {
}
public SecondClass TheProperty {
get {
return m_TheField;
}
}
ThirdClass m_TheField=new ThirdClass();
}
public partial class SecondClass {
protected void Update(/* parameters */) {
}
public SecondClass() {
}
}
The ThirdClass inherits from SecondClass, but is not exposed. The property exposed as an instance of type SecondClass, but in fact a field of type ThirdClass.
The method SecondClass.Update exposes to derived class only. That you can declare SecondClass public, not nested, but keep the updating of filed private.
What about a Nested Type.
public class FirstClass
{
private SecondClass TheField { get; set; }
public void SomeMethod()
{
TheField.Update( /*parameters*/);
}
private class SecondClass
{
public void Update( /*parameters*/)
{
// do something
}
}
}
Chris Sinclair answer is great,this is just another option
public sealed class FirstClass : SecondClass
{
public FirstClass()
{
}
public void SomeMethod(int j)
{
base.Update(j);
}
}
public abstract class SecondClass
{
public SecondClass() { }
protected void Update(int i)
{
Console.WriteLine(i.ToString());
}
}
this is just for the part of accessing the method through FirstClass