Consider this scenario:
public class Base
{
public int i;
}
public class Sub : Base
{
public void foo() { /* do stuff */}
}
And then I want to, given an instance of Base get an cloned instance of Sub (with i=17 in this case) so that I can call foo in the subclass.
Base b = new Base { i=17 };
Sub s = CloneAndUpcast(b);
s.foo();
However, how can I create CloneAndUpcast?
I am thinking that is should be possible to recursively clone all of Base-members and properties using reflection. But quite some work.
Anyone with better, neater ideas?
PS. The scenario where I am thinking about using this is a set of "simple" classes in a tree-like structure (no cyclic graphs or similar here) and all the classes are simple value holders. The plan is to have a stupid layer holding all values and then an similar set of classes (the subclasses) that actually contains some business-logic the value-holders shouldn't be aware of. Generally bad practice yes. I think it works in this case.
You could use AutoMapper to avoid the tedium of writing the copy constructors.
public class MyClass : MyBase
{
public MyClass(MyBase source)
{
Mapper.Map(source, this);
}
}
and you need to run this once when your application starts up
Mapper.CreateMap<MyBase, MyClass>();
You can download AutoMapper from https://github.com/AutoMapper/AutoMapper
Here's one way (out of many possibilities) that you could do something like you're asking. I'm not sure this is very pretty and can be kind of ugly to debug, but I think it works:
class BaseClass
{
public int i { get; set; }
public BaseClass Clone(BaseClass b)
{
BaseClass clone = new BaseClass();
clone.i = b.i;
return clone;
}
}
class SubClass : BaseClass
{
public int j { get; set; }
public void foo() { Console.WriteLine("in SubClass with value of i = {0}", i.ToString()); }
}
class Program
{
static void Main(string[] args)
{
BaseClass b1 = new BaseClass() { i = 17 };
BaseClass b2 = new BaseClass() { i = 35 };
SubClass sub1 = CloneAndUpcast<SubClass>(b1);
SubClass sub2 = CloneAndUpcast<SubClass>(b2);
sub1.foo();
sub2.foo();
}
static T CloneAndUpcast<T>(BaseClass b) where T : BaseClass, new()
{
T clone = new T();
var members = b.GetType().GetMembers(BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance);
for (int i = 0; i < members.Length; i++)
{
if (members[i].MemberType== MemberTypes.Property)
{
clone
.GetType()
.GetProperty(members[i].Name)
.SetValue(clone, b.GetType().GetProperty(members[i].Name).GetValue(b, null), null);
}
}
return clone;
}
}
Basically, as you suggested, you use reflection to iterate through the object's properties (I set i and j as public properties) and set the values accordingly in the cloned object. The key is using generics to tell CloneAndUpcast what type you're dealing with. Once you do that, it's pretty straightforward.
Hope this helps. Good luck!
Per the "Gang of Four" : "Favor composition over inheritance" and this is a perfect reason to do so...
If we have a SuperClass that looks like this:
public class SuperClass : Person
The SuperClass can easily decorate the Person class adding properties not found in Person class.
But what happens if the Superclass decorations are only for the GUI? For example a bool value indicating "Selected". We are still able to get all Persons from the DB in a List but we run into trouble trying to create the Superclass and merge the DB results.
foreach( var person in myPersonList){
var sc = new SuperClass();
sc.Selected = false;
sc=person;
}
The compiler complains because Superclass is not a Person to the compiler it's a Superclass. The only way to fill in the properties of the Person subclass is to iterate and set each one... like this.
SuperClass.Name = Person.Name;
SuperClass.Id = Person.ID;
Pretty tedious indeed. But there's a better way.... Don't make Superclass inherit from Person
public class SuperClass{
public Person ThisPerson {get;set;}
public bool Selected {get;set;}
}
This gives us "Containment" The Superclass now contains a Person class.
Now we can do this:
foreach(var person in MyPersonList){
var sc = new Superclass();
sc.Selected = false;
sc.Person = person;
}
The consumer of this class must now qualify the properties of the Superclass/Person like this...
forach(var sc in MySuperClassList){
var selected = sc.Selected;
var name = sc.Person.Name;
}
The beauty of this is that in the future, you can add any other container you want and it will NOT affect any other containers. You can also morph the Superclass to anything it contains. If each of the contained classes become Interfaces, then that's one step futher down the road.
Well, since b isn't a Sub, we can't "clone" it as one.
If Base has an appropriate combination of constructor and public properties to let a constructor in Sub ensure that its base would therefore have the same state as b, then we could use that.
I think I'd by-pass the whole thing though. If all we care about is that s have the same state in its base as b, and it has not other state that we're going to care about (or else we'd have to be passing it through to the CloneAndUpcast method), then do we need s at all?
A static method could take a Base and we could just use static public void foo(Base bc). We could even define it as an extension method static public void foo(this Base bc) and then code the call as b.foo(). The only thing this won't let us do that CloneAndUpcast() lets us do is access protected members.
Clone is a bad practice and your question is the reason for that (subclass cloning).
In general, you should just use copy cotrs instead and have the subclass accept a parent as a parameter.
public Base(){}
public Base(Base pSource){}
public Sub(){}
public Sub(Base pSource, other parameters...){}
public Sub(Sub pSource){}
Related
I want to apologize in advance if this is already answered. Since I did not know how to properly word it in the title, I may have missed another similar question. I saw this, which is similar but I don't think it is exactly the same, since it does not aim for a hierarchical structure like what I'll describe.
Say I have a base class and base field, and a method DoStuff() that acts on said field
class MyContainer
{
MyField field = new MyField();
protected virtual void DoStuff()
{
field.foo1 = "a";
field.foo2 = "b";
}
}
Now, I want to extend MyContainer, and I create MyContainerExt, which should also contain a derived version of MyField (MyFieldExt). MyContainerExt would override DoStuff() to do some extra stuff on MyFieldExt, but I also want the DoStuff() from my base class to be done: essentially, I want to do the 'base' stuff and initializations from the base MyContainer class, and add on top extra initializations that potentially require the new fields/properties added on the derived MyFieldExt.
To add on top of that, say now I want to have MyContainerExtExt, which has a field derived from MyFieldExt (i.e. MyFieldExtExt), which I want to do stuff on on top of what the parent classes were already doing.
To be honest, I have no idea how to tackle this in an organized and non-smelly way. To give you an idea, this would be what I would love to have (if you could override properties with derived types, which I know you cannot):
class MyContainer
{
abstract MyField Foo {get; set; }
protected virtual void DoStuff()
{
Foo.foo1 = "a";
Foo.foo2 = "b";
}
}
class MyContainerExt: MyContainer
{
override MyFieldExt Foo {get; set;} // I know, this is not legal
protected override void DoStuff()
{
base.DoStuff(); // The DoStuff() from the base class is applied
Foo.foo3 = "c"; // Potentially, foo3 and foo4 are fields added to MyFieldExt that
Foo.foo4 = "d"; // the base class MyField knows nothing about
}
}
class MyContainerExtExt: MyContainerExt
{
override MyFieldExtExt Foo {get; set;} // I know, this is not legal (again)
protected override void DoStuff()
{
base.DoStuff(); // The DoStuff() from the first derived class (MyContainerExt( is applied
Foo.foo5 = "e"; // Again, foo5 and foo6 are fields added to MyFieldExtExt that
Foo.foo6 = "f"; // the base class MyFieldExt knows nothing about
}
}
This may not make sense at first, but I would like to have a hierarchical structure where maybe I have multiple variations on each 'inheritance level':
> MyContainer
>> MyContainerExt1, MyContainerExt2...
>>> MyContainerExt1Ext1, MyContainerExt1Ext2, MyContainerExt2Ext1, MyContainerExt2Ext2...
and I want to take the common factor that these classes have to do on one of their fields: most (if not everything) that MyContainer needs to do on its MyField-type field, will need to be done by all of its childs, with the caveat that the childs of MyContainer also have derived versions of MyField. I would also like this to be relatively easy to expand: I would not like a solution that 'manages' to make this ladder work for up to 3 levels of inheritance like in the example. I may not need more, but I would like the code I am making to be expandable in the future in case of a MyContainerExtExtExt...Ext or whatever the case may be.
I am not fixed on the structure at all: it can be property-based, or private fields that the child classes have to re-implement, or whatever. I just want a relatively clean way to achieve initializing/working on the derived versions of MyField without copying all the lines from the parent's DoStuff() into the children's DoStuff() methods (which defeats the point of inheritance).
In case anyone is wondering, I need this for structuring my Models and ViewModels in a heavily hierarchical WPF application (ViewModel == MyContainer, Model == MyField), but this should not affect the question I think.
I am using .NET 4.5.2, by the way, so any new tricks are welcome up to that point.
EDIT:
I ended up with something very similar to InBetween's answer below. It is sort of what I was going for before asking, but it did not seem to sit right so I wanted to double check there was no standard/better way of doing it. My final structure is something the likes of:
class MyContainer
{
protected MyField Foo {get; set; }
public MyContainer()
{
Foo = new MyField();
}
protected virtual void DoStuff()
{
Foo.foo1 = "a";
Foo.foo2 = "b";
}
}
class MyContainerExt: MyContainer
{
public MyContainerExt()
{
Foo = new FieldExt(); // no need to override anything for this to work
}
protected override void DoStuff()
{
base.DoStuff(); // The DoStuff() from the base class is applied
MyFieldExt foo = (MyFieldExt)Foo; // The cast always works, since Foo is initialized as FieldExt
foo.foo3 = "c"; // Potentially, foo3 and foo4 are fields added to MyFieldExt that
foo.foo4 = "d"; // the base class MyField knows nothing about
}
}
class MyContainerExtExt: MyContainerExt
{
public MyContainerExtExt()
{
Foo = new FieldExtExt(); // no need to override anything for this to work
}
protected override void DoStuff()
{
base.DoStuff();
MyFieldExtExt foo = (MyFieldExtExt)Foo; // The cast always works, since Foo is initialized as FieldExtExt
Foo.foo5 = "e"; // Again, foo5 and foo6 are fields added to MyFieldExtExt that
Foo.foo6 = "f"; // the base class MyFieldExt knows nothing about
}
}
You can do the following. Given your base type;
class MyContainer
{
abstract MyField Foo {get; set; }
protected virtual void DoStuff()
{
Foo.foo1 = "a";
Foo.foo2 = "b";
}
}
There is no need to redeclare MyField in derived types, just cast it to the more specific type:
class MyContainerExt: MyContainer
{
protected override void DoStuff()
{
base.DoStuff();
var specificFoo = Foo as MyFieldExt; //this cast will always succeed
specificFoo.foo3 = "c";
specificFoo.foo4 = "d";
}
}
I have this construct.
public class SuperClass{}
public class InheritedClass : SuperClass{}
I want my instantiated Superclass to become an InheritedClass instance.
var superClassInstance = new SuperClass();
InheritedClass inHeritInstance = new InheritedClass(superClassInstance) ;
Somebody told me, that will not work without setting all properties in the Constructor.
Is that correct?
I want my instantiated Superclass to become an InheritedClass instance.
This is not possible. If you want it to be an instance of InheritedClass you must create one. You cannot upcast an instance of SuperClass.
That's true.. you can not Assign directly, In Constructor you have to transfer.
Instead..
you should create interface and implement the Interface into the class from where you are passing the value.
Now in into InheritedClass create constructor with the the interface as parameter, so whatever values are assigned into the First class, will be passed into InheritedClass
here you will have full access of First Class property.
Refer below dotnetfiddle url.
http://dotnetfiddle.net/8AgOCF
Yes, that is correct. There is no inbuilt way to provide your own baseclass object to promote to subclass. Each subclass will build it's own baseclass before it calls the subclasses' constructor on it.
You will need to write your own constructor in the subclass that copies all relevant data.
In a sense, yes, I'm afraid that is correct. A constructor is, by definition, creating a new instance. So anything from an existing instance is going to have to be copied to the new instance. It might be something like this:
public InheritedClass(SuperClass superClassInstance)
{
// base fields
Field1 = superClassInstance.Field1;
Field2 = superClassInstance.Field2;
Field3 = superClassInstance.Field3;
// local fields
Field4 = "some value";
// etc.
}
Or you can split the work between the classes, something like this:
public SuperClass(superClassInstance)
{
Field1 = superClassInstance.Field1;
Field2 = superClassInstance.Field2;
Field3 = superClassInstance.Field3;
}
then in the derived class:
public InheritedClass(superClassInstance)
: base(superClassInstance)
{
Field4 = "some value";
// etc.
}
It gets a lot easier the other way around, creating a SuperClass from InheritedClass, since any instance of InheritedClass is an instance of SuperClass and can polymorphically be interpreted as such:
SuperClass someObject = inheritedClassInstance as SuperClass;
(Note that this would not be a "new instance" so watch out for reference errors.) You might be able to do the same in reverse:
InheritedClass someObject = superClassInstance as InheritedClass;
But there is no guarantee that superClassInstance is also an instance of InheritedClass so you'd want to check for errors here. And, again, this is not a new instance.
Using composition instead of inheritance you can potentially achieve your goal with less code. For example, if you have a class like this:
public class InheritedClass
{
public SuperClass BaseObject { get; private set; }
// other fields
}
Then you can include a constructor in InheritedClass which just sets that one object:
public InheritedClass(SuperClass superClassInstance)
{
BaseObject = superClassInstance;
}
Again, however, note that this is not a new instance of SuperClass in the property but a reference to the existing one. To ensure a new one you'd still have to write your manual code (possibly in a .Copy() or .Clone() method on SuperClass?) to duplicate the instance.
In short, after all of my directionless brainstorming, cloning an instance field-by-field is going to require putting that field-by-field code somewhere.
Ok, here (a and b fields are for demo purposes):
public class SuperClass
{
object a;
public SuperClass()
{
a = "123";
}
// you need to have this
public SuperClass(SuperClass copy)
{
a = copy.a;
}
}
public class InheritedClass : SuperClass
{
object b;
public InheritedClass()
{
Init();
}
// and this
public InheritedClass(SuperClass super): base(super)
{
// bacause you can't call base() and this()
Init();
}
private void Init()
{
b = "456";
}
}
So you can do
var super = new SuperClass();
var inherited = new InheritedClass(super);
Proof.
I found a solution, which can at least copy all the properties automatically.
public InheritedClass(SuperClass superClassInstance)
{
foreach(var currentItem in superClassInstance.GetType().GetProperties())
{
GetType().GetProperty(currentItem.Name).SetValue(this,currentItem.GetValue(superClassInstance,null),null);
}
}
I have a group of classes (following strategy pattern) in my project. In the main function, I receive an enum value from the server and based on that I create an object of the base class type.
I am using switch/case statement to achieve this. I read somewhere that the Open/Closed principle does not allow opening a function to add a new case statement whenever a new class is added.
I am thinking of using a Activator.CreateInstance(). Is there any drawback to it.
Is there any other way to create an object from the enum type?
Adding example below even though it is not a full fledged Strategy pattern
abstract public class Mammal
{
public abstract void MakeSound()
}
class Cat:Mammal
{
public override void MakeSound()
{
Console.WriteLine("Meow");
}
}
class Dog:Mammal
{
public override void MakeSound()
{
Console.WriteLine("Bow");
}
}
Main()
{
MammalTypes mammalType = RecieveValueFromServer();
Mammal mammalBase
switch(mammalType) // need to make this dynamic depending upon Enum type
{
case MammalTypes.Cat:mammalBase = new Cat()
break;
case MammalTypes.Dog:mammalBase = new Dog()
break;
}
mammalBase.MakeSound()
}
One method for achieving true OCP might be the following:
Define an abstract method Is to force every concrete subtype of Mammal to specify whether it is appropriate for a given value of the enum:
abstract public class Mammal
{
public abstract void MakeSound();
public abstract bool Is(MammalTypes mammalType);
}
The implementations of Is in the subclasses would look like:
class Cat : Mammal
{
// other specific members
public override bool Is(MammalTypes mammalType)
{
return mammalType == MammalTypes.Cat;
}
}
class Dog : Mammal
{
// other specific members
public override bool Is(MammalTypes mammalType)
{
return mammalType == MammalTypes.Dog;
}
}
This being done, we can now create a MammalFactory class that, when given a Mammal enum value scans through the available classes and, when it finds a match, it returns an instance of that class:
public class MammalFactory
{
private readonly IEnumerable<Type> _mammalTypes;
public MammalFactory()
{
var currentAssembly = Assembly.GetExecutingAssembly();
_mammalTypes = currentAssembly.GetTypes()
.Where(t => typeof(Mammal).IsAssignableFrom(t) && !t.IsAbstract);
}
public Mammal Create(MammalTypes mammalType)
{
return _mammalTypes
.Select(type => CreateSpecific(type, mammalType))
.First(mammal => mammal != null);
}
public Mammal CreateSpecific(Type type, MammalTypes mammalEnumType)
{
var mammalInstance = (Mammal)Activator.CreateInstance(type);
return mammalInstance.Is(mammalEnumType) ? mammalInstance : null;
}
}
The final usage will look like this:
var mammalFactory = new MammalFactory();
var guessWhatMammal = mammalFactory.Create(MammalTypes.Cat);
This fully complies to OCP. It is only necessary to create a new Mammal class for it to be automatically wired and ready to use within the application. (no need to modify anything else in the application, except for the enum itself)
There are some problems with this approach:
it only scans the currently executing assembly for Mammal types
it has to create an instance of Mammal every time it needs to test whether that type is appropriate
While these issues can be addressed, one is still left: complexity.
This is complex because:
we've doubled the amount of code needed
the auto-wiring might be confusing for people new to the project
I think the conclusion is this: design patterns are not strict rules. It's not worth doing something just to conform to a given design.
Instead, we have to be pragmatic and find that perfect balance between pattern conformance and usefulness/simplicity/readability. This heavily depends on the problem we attempt to solve and in many cases it might very well be the switch statement you presented in the question.
You could use a Dictionary from the enum type to a function. The functions creates your strategy object:
public delegate Strategy StrategyFactory();
var strategyFactories = new Dictionary<MyEnum, StrategyFactory>();
This dictionary used to create your objects based on enum values:
var newStategy = strategyFactories[myEnumValue]();
the factory functions need to be added to the dictionary somehow. For that you can expose register (and maybe unregister) methods.
You could create an Attribute that takes the Type that the enum value represents and apply it to the enum field like so:
enum MyEnum {
[Creates(typeof(FooStrategy))]
Foo,
[Creates(typeof(BarStrategy))]
Bar,
// etc.
}
[AttributeUsage(AttributeTargets.Field, Inherited=false, AllowMultiple=false)]
sealed class CreatesAttribute : Attribute {
public Type TypeToCreate { get; private set; }
public CreatesAttribute(Type typeToCreate) {
TypeToCreate = typeToCreate;
}
public static IDictionary<T, Func<U>> GenerateLookup<T,U>() {
var query = from field in typeof(T).GetFields()
let creates = field.GetCustomAttriubtes(typeof(CreatesAttribute), false) as CreatesAttribute[]
let method = CreationMethod(typeof(U)) // create your type here
let key = (T)field.GetValue(null)
select new { Key = key, Method = method };
return q.ToDictionary(item => item.Key, item => item.Method);
}
}
The part left up to you is how you want to create an instance of your class. If they all have the same constructor, then this method will be easy as you can call Type.GetConstructor(Type[]) and then call Invoke your ConstructorInfo instance, or you could use an IoC container and resolve an instance from the type, not worrying so much about constructors with different parameters.
Then you can create a static class for extension methods on your enum:
public static class MyEnumExtensions {
static readonly IDictionary<MyEnumType, MyBaseStrategyType> lookup =
CreatesAttribute.GenerateLookup<MyEnumType, MyBaseStrategyType>();
public static MyBaseStrategyType CreateInstance(this MyEnumType key) {
return lookup[key](/* pass any common constructor values */);
}
}
Finally you would call it like so:
var myEnum = MyEnumType.Foo;
var strategy = myEnum.CreateInstance();
// use your strategy
This should keep you from violating the open/closed principle and allow you to add as many classes as you want and only change the Enum which can be made generic enough to create an instance of the strategy directly from the enum value.
Please tell me what is of parent object instantiating with child class like:
public class A
{
public A()
{
Console.WriteLine("A");
}
public virtual void method()
{
Console.WriteLine("AM");
}
}
public class B : A
{
public B()
{
Console.WriteLine("B");
}
public new void method()
{
Console.WriteLine("BM");
}
public void method1()
{
Console.WriteLine("BM1");
}
}
class Program
{
static void Main(string[] args)
{
A obj = new B();// what is use of it?
obj.method();
Console.Read();
}
private void methodP1()
{
}
}
please tell me what is use of
Parent obj = new Child();
as i we can only call to only public methods of parent class which is possible using
Parent obj = new Parent();
is it possible: Child obj = new Parent() ?
please tell me what is use of Parent
obj = new Child(); as i we can only
call to only public methods of parent
class which is possible using Parent
obj = new Parent();
This is the basis for polymorphism: Imagine you have several child classes that inherit from you parent class. You want to use all these child classes through the interface / methods defined on your parent class, without worrying about the implementation details in each child class (each might do something different, but with the same overall semantics).
This is possible because the child class has a IS A relationship with its parent class since child inherits from parent.
In your example, B is-a A, but A is-not-a B.
The above is of use when the code using the reference to B can only understand (or needs to understand) types of A. B is a specialisation of A. Imagine something like (pseudo-code)
Shape s;
if (x == 1) {
s = new Square();
}
else {
s = new Triangle();
}
// following code knows only about Shapes
s.draw();
s.calculateArea();
The following code doesn't need to know if s is a square or a triangle, just that it's a shape. What use is that ? If you call s.draw(), the shape itself determines how it's going to look. The code calling it doesn't know or care.
This is a key point of object-oriented programming. Asking objects to do things for you rather than determine yourself what's needed.
Note that your final question doesn't intuitively make sense when using this example.
Shape s = new Square(); // fine
vs
Square s = new Shape(); // can you instantiate a "shape" and why then do you decide it's a square?
BrokenGlass's answer is correct. However, your sample will have different behaviour depending upon whether you declare obj as type A or B.
In the case of A obj = new B(); the program will output A B AM because the compiler is linking to the virtual method A.method, which class B then inherits.
In the case of B obj = new B(); the program outputs A B BM because the compiler is directed to use the new method B.method().
If B.method() was instead declared as public override void method(), then the output would always be A B BM regardless of whether obj was declared as type A or type B.
Thus your example does not show polymorphism in the classic sense, as the method called on instances of type B depends on the type of the variable to which the instance is assigned. This can make debugging fun and interesting.
The reason that you would use polymorphism is so that you can pass a more specific object to an entity that only requires a more general object. The entity that receives the object only cares about the public interface that is exposed, not the details of how the methods in that interface are carried out. Here's a simple class hierarchy:
public class Animal
{
public virtual string GetFood()
{
return "Food";
}
}
public class Monkey : Animal
{
public override string GetFood()
{
return "Bananas";
}
}
public class Cow : Animal
{
public override string GetFood()
{
return "Grass";
}
}
And here's how you could use the polymorphism:
class Program
{
static void Main(string[] args)
{
Animal[] animalArray = { new Monkey(), new Cow() };
foreach (Animal a in animalArray) {
WhatDoIEat(a); // Prints "Bananas", then "Grass"
}
}
static void WhatDoIEat(Animal a)
{
Console.WriteLine(a.GetFood());
}
}
If you have to use only the methods on the parent class, you can go ahead and instantiate it. The object of a child class is to add functionality to the parent class while keeping the parent intact. Instantiating the parent through the child without further use of the child functionality does not make sense.
There's no use in simple examples like yours, where the scope of usage for the variable is limited. But it's important to understand that in .NET variables has types that are static, known at compile time and even if obj keeps a reference to Child class, it is still typed as Parent.
And when you have method that requires Parent, you can pass obj (with type Child) to it (and it still behaves like Child) - this is an example of Child being referred by Parent type.
Child obj = new Parent() is not possible, Parent is not a Child, compiler wouldn't let you assign object to variable of incompatible type.
Say you have a parent class called Animal and child classes called Dog, Cat, and Lizard. Each class has a method call makeSound(). Then when you say Animal a1 = new Dog(); and Animal a2 = new Cat(), a1.makeSound() will bark and a2.makeSound() will meow.
The technical term for this behavior is called polymorphism. It is useful for code reuse. You only need to write code once for an application that has Animals makeSound() when they are happy, instead of separate code for each animal type.
Another use of polymorphism is hiding your code's implementation from other users. For example you can show other users that you are using a List and then you have the choice to implement the List as a LinkedList or as an ArrayList. You can also choose a LinkedList and then at a later time switch to an ArrayList without effecting your users.
You also can't say Dog d = new Animal() because a Dog is an Animal but an Animal is not necessarily a Dog.
When You Know Common features about a Class which inherits from and when you dont know the exact child you can put the data on Parent class, whenever you knew about the child class you can assign those values on it.
I'm currently altering a widely used class to move as much of the expensive initialization from the class constructor into Lazy Initialized properties. Below is an example (in c#):
Before:
public class ClassA
{
public readonly ClassB B;
public void ClassA()
{
B = new ClassB();
}
}
After:
public class ClassA
{
private ClassB _b;
public ClassB B
{
get
{
if (_b == null)
{
_b = new ClassB();
}
return _b;
}
}
}
There are a fair few more of these properties in the class I'm altering, and some are not used in certain contexts (hence the Laziness), but if they are used they're likely to be called repeatedly.
Unfortunately, the properties are often also used inside the class. This means there is a potential for the private variable (_b) to be used directly by a method without it being initialized.
Is there a way to make only the public property (B) available inside the class, or even an alternative method with the same initialized-when-needed?
This is reposted from Programmers (not subjective enough apparently):
https://softwareengineering.stackexchange.com/questions/34270/best-methods-for-lazy-initialization-with-properties
Well, my recommended solution would be to tell your coworker to use the property, not the field. But you could idiot-proof it to some degree like this:
public class ClassA
{
private Lazy<ClassB> _b = new Lazy<ClassB>(() => new ClassB());
public ClassB B
{
get
{
return _b.Value;
}
}
}
Now it's pretty hard to screw up.
You could consider pushing the lazy properties into a base class to avoid direct access to the backing variable. Not ideal I know. I've always thought this was something lacking in C# i.e. direct support for lazy properties.
#chibacity posted (and subsequently) deleted [and later undeleted :P] an alternative option using an abstract base class. While it may not be ideal in terms of code distribution it does provide a nice encapsulation removing a lot of code clutter making for a cleaner and more succinct ClassA. For instance, you could consider combining the techniques to achieve both goals:
public class ClassB { /* Class to be lazily instantiated */ }
public abstract class BaseA
{
private Lazy<ClassB> _b = new Lazy<ClassB>(() => new ClassB());
public virtual ClassB B { get { return _b.Value; } }
}
public class ClassA : BaseA
{
public override ClassB B { get { return base.B; } }
}
At first glance, it seems like this is more long winded, but when you consider that ClassA which is the class you would be working in and with, this now means that all your references are going through the same property - there is no extraneous unnecessary field causing potential confusion, there's no bypassing the property to reference _b directly and there's no need to tell your coworker which to use... there's only one.
Not saying this is the right way to do this or that this is a pattern that should or shouldn't be followed, I'm just pointing out the advantages of what #chibacity suggested that may otherwise go unnoticed.
It would be nice if you could have implicit lazy loaded properties without having to refer to B.Value... for instance:
[Lazy]
public ClassB B { get; }
or for objects without parameterless constructors
[Lazy(() => new ClassB("Hello", "World"))]
public ClassB B { get; }
or perhaps as #chibacity suggested in a comment
public ClassB B { lazyget; }
or
public ClassB B { lazyget : new ClassB(); }
Alas, I don't think any of these are currently available solutions in any form...