I have the following problem:
The base class expects to receive some data but the data is initialized by the derived class constructor which in C# is called after the base constructor was called.
Context / What I'm trying to solve:
Let's call the base class Track, its role is to build a mesh that represents a track for a video game.
The derived classes, e.g. Track1 each fetch track data from a particular file format, with significant differences that forbids implementing the whole code in base class Track.
The main job of Track is to abstract the data incoming from derived classes and for this it has abstract members that derived classes have to implement, e.g. int GetVertexCount, Vector3 GetVertex(int).
Think more of less of it being an IPicture interface that can load from different formats, e.g. BMP, JPEG, and return the whole thing as an abstraction.
The problem I am facing:
In C#, base class constructors are called before derived class constructor, but I must initialize something in the derived class constructor that in turn I must pass to the base class constructor. And while I'm on it, I would like to have members to be immutable, i.e. readonly.
Question:
How can I run some code in derived class constructor first, so I can pass the result to the base constructor ?
Answer:
Following #Kit answer here's how I ended up doing and it's just fine:
Ironically, it ended up being a C-like API :)
Assuming you don't need an instance of your derived class to do the logic you want, you can call a static method from your derived constructor prior to calling the base constructor.
Here is a simplistic example
public class Base
{
protected Base(SomeType data)
{
// base logic using data
}
}
public class DerivedOne : Base
{
public DerivedOne(int some, string data) : base(DerivedLogic(some, data))
{
...
}
private static SomeType DerivedLogic(int some, string data) => ...
}
public class DerivedTwo : Base
{
public DerivedTwo (string moreStuff) : base(DerivedLogic(moreStuff))
{
...
}
private static SomeType DerivedLogic(string moreStuff) => ...
}
This runs in the following order:
Static method DerivedLogic
Base class constructor (using the value from DerivedLogic)
Derived constructor
Now, that's slightly weird. What might be better is the derived logic not be a part of the derived class at all. What do I mean? I mean you have a third class that is passed into the derived constructor, and then on to the base constructor. That gives you the same effect.
public class Base
{
protected Base(SomeOtherType dataWrapper)
{
var data = dataWrapper.DerivedLogic();
// base logic using data
}
}
public class DerivedOne : Base
{
public DerivedOne(SomeOtherType otherType) : base(otherType)
{
...
}
}
Or calculate SomeType somewhere prior to calling any constructors and then pass it in. Either of these ways is a better design because it follows SRP:
Base class responsible for what it does.
Logic for constructing a track has that single responsibility.
Derived class has it's single responsibility.
There's not a really elegant way to do exactly what you're asking for, but I would question whether it's really necessary. It's usually a code smell to see logic in a constructor.
There are lots of other approaches you can take, like using a static Create() method.
class Derived : Base
{
private readonly object _o;
private Derived(object o, string s) : base(s)
{
_o = o;
}
public static Derived Create(string path)
{
var o = new object();// initialize from path
var s = o.ToString(); // get s from o.
return new Derived(o, s)
}
}
You could also consider using composition over inheritance:
class Base
{
private readonly string _s;
public Base(string s)
{
_s = s.ToLower();
}
}
class Derived
{
private readonly object _o;
private readonly Base _b;
public Derived(string path)
{
_o = new object();// initialize from path
_b = new Base(_o.ToString());
}
}
But it's really difficult to know which of these approaches might be appropriate without knowing what your actual goals and constraints are. You've told us how you want to solve your problem, and not what problem you're trying to solve.
Related
I have the following class:
class Base<T> where T : Base<T>
{
protected static string Source;
public static List<T> Read()
{
return GetResource(Source);
}
}
I want this class as baseclass for its functionality but every derived class has to have a different Source. My problem is that I can't assure the Source is set before Read is called. I know I could ask if the Source is set before GetResource is called but that's not the point. I need it to be set before any static member of my class is called.
Generic parameters can't have static Members so I can't take it from there.
I tried setting the Source in the derived class's static constructor but that will only be called when I call a member that is in the derived class and not in the Base.
I tried using a overridable method inside of the static Base constructor but such a method has to be static as well and static methods can't be overwritten.
When I set the Source manually, there is a chance that the Read-Function has already been called, so I have to set the Source before it can be called.
I know I could give Source as a parameter in Read but I want Read to be used without parameters.
Is there any way I can assure that the Source is Set before any other Member of my class is called, so that any dependent code is inside the derived class and doesn't have to be called by anyone using a derived class?
I basically want it to work like this:
class Derived : Base<Derived>
{
// somehow set Source
Source = "This is my source";
}
class User
{
private List<Derived> MyResources;
public User()
{
MyResources = Derived.Read();
}
}
Note: the Source is basically a SQL statement so an Attribute or something like that wont be sufficient I think.
Ok, I found an answer. It is not as pretty as I hoped it would be but its the best I could come up with.
I will use an interface to force an Instance of T to have a certain method that provides my source.
interface ISource
{
string GetSource();
}
I then implement that into my base class as such:
class Base<T> where T : Base<T>, ISource, new()
{
public static List<T> Read()
{
// here I create an Instance to be able to call the Methods of T
string source = (new T()).GetSource();
return GetResource(source);
}
}
The derived class:
class Derived : Base<Derived>, ISource
{
public string GetSource()
{
return "This specific source";
}
}
Usage as such:
class User
{
public User()
{
List<Derived> myResources = Derived.Read();
}
}
This of course will lead to every instance of Derived having the GetSource-method but for my scenario thats not a big deal.
Also, since it creates an instance in the Read-method, this could be time consuming depending on the constructor of Derived. In my scenario it only has the standard constructor.
So use with caution.
I have a generic class that deals with widgets that can be deserialized from strings. Instances of the generic class will take the type of one of these widgets as a template parameter, and then create these widgets from strings. I wish to use the covariance properties of C#'s generics to write code like WidgetUser<IWidget> to deal with objects that may be WidgetUser<RedWidget> or WidgetUser<BlueWidget>. The problem is that to create a widget from a string inside of WidgetUser<T>, I'm forced to add new() as a guard. This makes WidgetUser<IWidget> an invalid type. Currently, I have code like this:
interface IWidget
{
// Makes this widget into a copy of the serializedWidget
void Deserialize(string serializedWidget);
}
class WidgetUser<T> where T : IWidget, new()
{
public void MakeAndUse(string serializedWidget)
{
var widget = new T();
widget.Deserialize(serializedWidget);
Use(widget);
}
}
With this code, I can make WidgetUser<BlueWidget> just fine, because BigWidget satisfies new(). I cannot write WidgetUser<IWidget> because instances of IWidget (or an equivalent abstract class) are not guaranteed to work with new(). A workaround could be this:
abstract class WidgetUser
{
public abstract void MakeAndUse();
}
class WidgetUser<T> : WidgetUser
where T : IWidget, new()
{
/* same as before but with an 'override' on MakeAndUse */
}
With this code, I can create a WidgetUser<BlueWidget> then write code that deals with just WidgetUser. I could have similar code with an abstract class BaseWidget instead of IWidget that accomplishes almost the same thing. This is functional, but I suspect there is a more direct approach that doesn't force me to define a dummy class. How can I convey my intent to the type system without creating dummy classes or extra factories. I just want an interface that says "you can make one of these from a string".
TL;DR:
Is there some way to write an interface or abstract class that lets me create an instance from a string but doesn't require me to have new() as a guard on WidgetUser<T>?
The problem here is that your Deserialize() method should be a static method. Therefore it should not be a member of IWidget itself - it should be a member of a factory interface, or it should be a static member of a concrete Widget class which is called from a concrete factory method. I show the latter approach below.
(Alternatively, you could use a Func<IWidget> delegate to specify it, but it's more usual to provide a full factory interface.)
So I suggest you create the factory interface:
interface IWidgetFactory
{
IWidget Create(string serialisedWidget);
}
Then remove the Deserialize() from IWidget:
interface IWidget
{
// .. Whatever
}
Then add a static Deserialize() method to each concrete implementation of IWidget:
class MyWidget: IWidget
{
public static MyWidget Deserialize(string serializedWidget)
{
// .. Whatever you need to deserialise into myDeserializedObject
return myDeserializedObject;
}
// ... Any needed IWidget-implementing methods and properties.
}
Then implement the factory for your concrete widget class using the static Deserialize() method from the concrete widget class:
sealed class MyWidgetFactory : IWidgetFactory
{
public IWidget Create(string serialisedWidget)
{
return MyWidget.Deserialize(serialisedWidget);
}
}
Then add a constructor to your WidgetUser class which accepts an IWidgetFactory and use it in MakeAndUse():
class WidgetUser
{
public WidgetUser(IWidgetFactory widgetFactory)
{
this.widgetFactory = widgetFactory;
}
public void MakeAndUse(string serializedWidget)
{
var widget = widgetFactory.Create(serializedWidget);
Use(widget);
}
private readonly IWidgetFactory widgetFactory;
}
Note that in this scenario, you no longer need the type argument for WidgetUser, so I have removed it.
Then when you create the WidgetUser you must supply a factory:
var widgetUser = new WidgetUser(new MyWidgetFactory());
...
widgetUser.MakeAndUse("MySerializedWidget1");
widgetUser.MakeAndUse("MySerializedWidget2");
Passing in a factory allows a lot more flexibility.
For example, imagine that your serialization scheme included a way of telling from the serialized string which kind of widget it is. For the purposes of simplicity, assume that it starts with "[MyWidget]" if it's a MyWidget and starts with ["MyOtherWidget"] if it's a MyOtherWidget.
Then you could implement a factory that works as a "virtual constructor" that can create any kind of Widget given a serialization string as follows:
sealed class GeneralWidgetFactory: IWidgetFactory
{
public IWidget Create(string serialisedWidget)
{
if (serialisedWidget.StartsWith("[MyWidget]"))
return myWidgetFactory.Create(serialisedWidget);
else if (serialisedWidget.StartsWith("[MyOtherWidget]"))
return myOtherWidgetFactory.Create(serialisedWidget);
else
throw new InvalidOperationException("Don't know how to deserialize a widget from: " + serialisedWidget);
}
readonly MyWidgetFactory myWidgetFactory = new MyWidgetFactory();
readonly MyOtherWidgetFactory myOtherWidgetFactory = new MyOtherWidgetFactory();
}
Note that this is generally not the best way to do things - you are better using a Dependency Container such as Autofac to manage this kind of thing.
I would implement WidgetFactory and call WidgetFactory.Create<T>(serializedWidget) to avoid the usage of new T()
(Simplified) Scenario:
public class BaseClass
{
public int BaseClassInt {get; set;}
public BaseClass(int pBaseClassInt)
{ this.BaseClassInt = pBaseClassInt; }
}
public class DerivedClass : BaseClass
{
public int DerivedClassInt {get; set;}
public DerivedClass (int pBaseClassInt, int pDerivedClassInt) : base(pBaseClassInt)
{ this.DerivedClassInt = pDerivedClassInt; }
}
If I want to instantiate a DerivedClass-object I have to pass all arguments required to create a BaseClass-object and a DerivedClass-object. Also for every BaseClass-constructor I have to (at least should in my concrete case) provide a constructor with the same arguments in the derived class, plus arguments for the derived class properties. Then, if I change or delete a constructor in the base class I have to change or delete the corresponding contructor in the derived class(es).
I wonder if it is possible to use a constructor for the derived class which accepts a base class-object as an argument:
public DerivedClass(BaseClass pBaseClassObejct, int pDerivedClassInt)
{
// to make clear what I intend to do - looks silly of course
this = (DerivedClass)pBaseClassObject;
this.DerivedClassInt = pDerivedClassInt;
}
This could be called:
DerivedClass DerivedClassObject = new DerivedClass((new BaseClass(1),2);
If constructors in the base class would change, I wouldn´t have to mind it for the derived class. Is there any way to achieve this?
Think about this line for a moment:
this = (DerivedClass) pBaseClassObject;
Let's ignore the fact that you cant set this directly that way, and focus on the rest.
Imagine Giraffe and Elephant are both implementations of AfricanAnimal:
// By extension, ellie is also an AfricanAnimal
Elephant ellie = new Elephant();
// assume ellie is passed in as a param here (she can
// be, because she is an AfricanAnimal after all!):
public Giraffe(AfricanAnimal ellie)
{
this = (Giraffe) ellie; // Can't do this!
}
You can't (and would not want to) force ellie into being a giraffe, because a giraffe may have properties etc. that ellie lacks, and ellie may have properties that Giraffes don't have. Yet, using an AfricanAnimal as your parameter type there, would allow for just that.
Note: You could write that code and pass a Giraffe in, and all would be fine, but then again, that makes little sense; then you might as well use the Giraffe type as the parameter.
If you replace this with an instance variable, you would be able to compile with something like the following...
public Giraffe(AfricanAnimal ellie)
{
this.varOfTypeGiraffe = (Giraffe) ellie;
}
... but as soon as you run it with an Elephant as a a prameter, you will get an exception similar to:
InvalidCastException: Unable to cast object of type 'Elephant' to type 'Giraffe'.
TL;DR: This is a bad idea. Don't even try.
You cannot make a base constructor run from inside the body of any derived method (including the derived constructor). Even if you could, a base instance would not have retained any information about which constructor was used to instantiate it so there would be no way to know which base constructor should be called.
The above refers to the general case where a base constructor can potentially modify application state not directly related to the base class (e.g. by changing the value of static fields somewhere). You could use reflection to copy property values from a base instance to the derived instance being created, but this is practically unworkable because
It requires that you create a base instance in the first place -- what if the base is abstract, or if creating one has side effects?
You need a guarantee that the base constructor does not modify application state. But the aim here is to be independent of what the base constructors do, so you are back to square one.
No, that is not possible and should not be, because it doesn't make sense.
If it was possible and you deleted/changed the base class constructor, you would still need to change the code which creates the base class object that you would use as an argument to the derived class constructor.
Also, not all base classes are concrete. You would not be able to create an abstract base class, right?
This feature is not available. I think what you want is a little like this:
Suppose C# had a keyword allbaseargs and allowed code like this:
public class DerivedClass : BaseClass
{
public int DerivedClassInt { get; set; }
public DerivedClass (allbaseargs, int pDerivedClassInt)
: base(allbaseargs)
{
DerivedClassInt = pDerivedClassInt;
}
}
Then this could only work if BaseClass had only one (accessible) instance constructor.
The compiler should then examine the sole base constructor and substitute the magical word allbaseargs with the parameters of that constructor.
However, C# does not have this feature, and you would have to hand-code everything, which includes changeing all : base(...) calls of all derived classes when the constructor signature changes.
It is allowed to have the signature:
public DerivedClass(BaseClass pBaseClassObejct, int DerivedClassInt)
like you suggest, but you would not be able to chain the : base(...) easily. You would have to equip BaseClass with a construtor that took another instance in and copied all "state" (all instance properties and fields and such) from that other instance to "this". I do not recommend that solution.
This might be help!
Solution A: Create Inherit instead of base!
public static class Test
{
public static T Foo<T>(string text, int num) where T : BaseClass
{
T #base = (T)Activator.CreateInstance(typeof(T), new object[] { text, num });
//...
return #base;
}
public static void Main()
{
InheritClass inherit = Foo<InheritClass>("Hi there", 10);
}
}
Solution B: Copy base to inherit
public static class Test
{
public static TInherit As<TBase, TInherit>(this TBase #this) where TInherit : TBase
{
var type = typeof(TInherit);
var instance = Activator.CreateInstance(type);
foreach (var property in type.GetProperties())
if (property.CanWrite)
property.SetValue(instance, property.GetValue(#this, null), null);
return (TInherit)instance;
}
public static BaseClass Foo(string text, int num)
{
BaseClass #base = new BaseClass(text, num);
//...
return #base;
}
public static void Main()
{
InheritClass inherit = Foo("Hi there", 10).As<BaseClass, InheritClass>();
}
}
Notes: you can have simple 'As()' found here, but i prefer mine (where Inherit : TBase), where it's more safe and support converting base to inherit of inherit class.
I have no practical experience with OO design, thus I am hesitant as to the solution I adopted for the following problem:
I have to process network text files that come from N different sources, in different formats - with the processing consisting in the classical reading, computations, and insertion into database.
The solution I devised was to create a class that defines all functionalities/behaviors that are core/file-format-independent, and create derived classes from the latter where each contain the appropriate format-reading logic, according to the file-type the given class handles.
All files are read via File.ReadAllLines(), what differs is mapping fields from the file into the main object's variables. So I did this by defining an event in the base class, that is called after File.ReadAllLines(), and all derived classes attach their mapping logic to the inherited event.
But I understand this solution is not correct design-wise. First of all, there is no meaning in instantiating the base class, so it should be abstract. The reason I did not make it abstract is that the construction code for all the derived objects is the same, so I defined it as the base constructor. Should I declare an "Initialize" method in the abstract class and simply call it in every derived class's constructor? (looks weird...)
Perhaps interfaces? I don't see how using an interface would give me any benefits here, besides it will not solve this "constructor" problem...
What is the correct solution?
Code demonstration of my scenario:
public delegate void myDelegate(object parameter);
class Base
{
#region Attributes
...
#endregion
public Base(object p)
{
//initialization code
...
}
#region Methods
protected void m1() { }
protected void m2() { }
...
#endregion
public event myDelegate myEvent;
}
class Child1
{
public Child1(object o) : base(o)
{
this.myEvent += new myDelegate(ChildMethod);
}
public void ChildMethod(object o)
{
...
}
}
First of all, there is no meaning in instantiating the base class, so it should be abstract. The reason I did not make it abstract is that the construction code for all the derived objects is the same, so I defined it as the base constructor.
You still can make the base class abstract yet have common constructor logic in the base class constructor. I see in your code you've already figured out how to call the base class constructor; that's all you need to do.
abstract class Base {
public Base(object o) { }
public abstract void M();
}
class Derived : Base {
public Derived(object o) : base(o) { }
public override void M() { }
}
I have a base class that has a private static member:
class Base
{
private static Base m_instance = new Base();
public static Base Instance
{
get { return m_instance; }
}
}
And I want to derive multiple classes from this:
class DerivedA : Base {}
class DerivedB : Base {}
class DerivedC : Base {}
However, at this point calling DerivedA::Instance will return the same exact object as will DerivedB::Instance and DerivedC::Instance. I can solve this by declaring the instance in the derived class, but then every single derived class will need to do that and that just seems like it should be unneccessary. So is there any way to put all this in the base class? Could a design pattern be applied?
There's one really icky way of doing this:
class Base
{
// Put common stuff in here...
}
class Base<T> : Base where T : Base<T>, new()
{
private static T m_instance = new T();
public static T Instance { get { return m_instance; } }
}
class DerivedA : Base<DerivedA> {}
class DerivedB : Base<DerivedB> {}
class DerivedC : Base<DerivedC> {}
This works because there's one static variable per constructed type - e.g. List<string> is a different type to List<int> and so would have separate static variables.
I've taken the opportunity of making it an instance of the derived class as well - I don't know whether that's what you want or not, but I thought I'd at least make it available for you :)
In general though, this is a nasty thing to do. Static variables aren't really designed for this kind of use - I've just abused a feature of generics to get "sort of" the behaviour you asked for.
Also note that Base<DerivedA>.Instance will return the same result as DerivedA.Instance - the property/variable don't "know" that you're using DerivedA.Instance. I don't know whether or not that's important to you.
With the extra non-generic class, you can write:
Base t = DerivedA.Instance;
t = DerivedB.Instance;
If you don't need that, take it out :)
Static methods does not support polymorphism, therefore, such a thing is not possible.
Fundamentally, the Instance property has no idea how you're using it. And a single implementation of it will exist, as it's static. If you really wanted to do this, this "not recommended" solution is available (I got the idea from Jon's solution):
private static Dictionary<Type, Base> instances = new Dictionary<Type, Base>();
public static T GetInstance<T>() where T : Base, new() {
Type ty = typeof(T);
T x;
if (instances.TryGetValue(ty, out x)) return x;
x = new T();
instances[ty] = x;
return x;
}
Short answer: not that I'm aware of. Static members are always nonvirtual and do not readily support polymorphism.
However, you should also ask yourself why you are doing this. Normally, static members are shared resources that every instance of that class (including the derived classes) will find useful. However, when you make a static instance, you are usually building towards a singleton pattern. In this case, you usually want to seal the class so you can't have derived classes, thus rendering the entire point moot. Thus, you should really be analyzing why you are wanting to do this and solve that problem instead.