If you have a method that takes a Fruit then you can pass it an Apple and know there will be no problems Let's simplify your code. You have class B { public T Another { get; set; } } class Fruit : B {} class Apple : Fruit {} class Orange : Fruit {} Now, Apple. Another is of type Fruit, not of type Apple.
It has to be of type Fruit, because you could have a method void AddAnOrange(Fruit f) { f. Another = new Orange(); } This has to work even if you pass in an Apple the contract of Fruit is that a Fruit refers to any other Fruit not "a fruit refers to another fruit of some more derived type that is not known until runtime If you need to model the relationship "An apple refers to another apple, an orange refers to another orange", then don't do it by saying "A fruit refers to another fruit"; that's not capturing the thing you want to model correctly, and will just cause you pain later.
If you have a method that takes a Fruit then you can pass it an Apple and know there will be no problems. Let's simplify your code. You have class B { public T Another { get; set; } } class Fruit : B {} class Apple : Fruit {} class Orange : Fruit {} Now, Apple.
Another is of type Fruit, not of type Apple. It has to be of type Fruit, because you could have a method void AddAnOrange(Fruit f) { f. Another = new Orange(); } This has to work even if you pass in an Apple -- the contract of Fruit is that a Fruit refers to any other Fruit, not "a fruit refers to another fruit of some more derived type that is not known until runtime".
If you need to model the relationship "An apple refers to another apple, an orange refers to another orange", then don't do it by saying "A fruit refers to another fruit"; that's not capturing the thing you want to model correctly, and will just cause you pain later.
You could take the following approach:- public interface IPreviousInstance { T PreviousInstance { get; set; } } public class DataClass : IPreviousInstance { public DataClass PreviousInstance { get; set; } public bool ABoolProperty { get; set; } } public class DerivedDataClass : DataClass, IPreviousInstance { public new DerivedDataClass PreviousInstance { get; set; } public string AStringProperty { get; set; } }.
I don't think abstract properties (as PreviousInstance in your example) can be implemented as automatic properties. Still +1 because I think your approach is the best. – ShdNx Jan 13 '10 at 18:05 It's not an abstract property, it's an interface property.
I've checked and the code does compile. – Adam Ralph Jan 13 '10 at 18:07 Thanks Adam, I did consider this type of solution but my library is to be used by my team and if they derive there own data they would have to know to implement the interface, when what I need is an automatic way of changing the type of PreviousInstance. – Gavin Uttley Jan 14 '10 at 9:42 hi Gavin, although they would need to know to implement the interface, would they not also have to know to implement the abstract class?
– Adam Ralph Jan 16 '10 at 22:46.
Well what you want is not possible basically because multiple inheritance is not allowed. What you can do is carrying over the generic type parameter from the base class, as in public class DataClass : BaseClass Depending on what you want to achieve, this could do the trick for you. Remember that generics are not intended to be used like template text for source code.
At the moment the only way I can see is to introduce another layer in the chain: public abstract class AbstractDataClass : BaseClass { public bool ABoolProperty { get; set; } } public class DataClass : AbstractDataClass { } public class DerivedClass : AbstractDataClass { public string AStringProperty { get; set; } } Though I admit it is very clunky especially when you start getting into increasing levels of the hierarchy.
You could try shadowing the property as in the following: public class DerivedDataClass : DataClass { new public DerivedDataClass PreviousInstance { get { return (DerivedDataClass)base. PreviousInstance; } set { base. PreviousInstance = value; } } } If PreviousInstance is not of the correct type, you will get an error.
Note: you can't refer to an instance of DerivedDataClass as its base type DataClass, because then it will use the DataClass version of PreviousInstance, and circumvent the shadowing.
Thanks for the response guys, but non of the solutions quite meet what I need. The library I am making is to be used by my team and if they need to derive their own data then it needs to be automatic so they don't have to have indepth knowledge of having to implement interfaces or shadow a property. What I have decided to do is add another class decleration so that the end developer can use the generic (for derived classes) or non generic for straight use in their application.
For example: public class DataClass : BaseClass { public bool ABoolProperty { get; set; } } public class DataClass : DataClass { }.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.