not sure if this maybe is a codeReview post but here we go:
My goal is to re-implement the way objects are copied within our application. We have multiple base classes:
CoreList<T> // for all list classes
BasicReference // for all reference classes
CoreObject // for all "normal" domain objects
All classes inherit from these base classes. Right now the copy method is implemented on the CoreObject class and will go through the object tree via reflection, looking at each property type and select the correct way to copy the type and finally returning always CoreObject.
There are some problems which I don't like about that approach, which is why I would like to change it:
After copying an domain object you always have to cast it "back" to the original type, for example: Animal = animal.Copy() as Animal;
All logic to copy each type is within the CoreObject class even though it should not know about other base classes.
So my first attempt was to introduce a interface:
public interface IObjectCopy<out T>
{
T Copy();
}
Which then should be implemented on all base classes. Then every class is responsible for the way it is copied. For example (pseudo code):
public class CoreObject : IObjectCopy<CoreObject>
{
public virtual GerCoreObject Copy()
{
foreach (var prop in properties)
{
if (prop.IsNoSimpleType)
{
(prop as IObjectCopy).Copy()
}
}
}
That solves the copy-responsibility problem, in addition inherited classes can take care of the copy logic themselves.
Unfortunately that does not solve the return type, I still have to cast it to the correct type. I did not think of a better solution to solve this. Any ideas?
This problem could be solved in OO using covariant return types. Unfortunately C# does not support covariant return types like Java and C++, requiring it to always break type safety.
Without breaking type safety (casting) in C# this is unfortunately not possible.
Here are two possible options:
//explicit interface implementation
public class Animal : CoreObject, IObjectCopy<Animal>
{
Animal IObjectCopy<Animal>.Copy()
{
return (Animal) base.Copy();
}
}
//does not require an explicit cast
IObjectCopy<Animal> animalCopy = myAnimal;
Animal copiedAnimal = animalCopy.Copy();
//second option: shadow the original method and cast inside the object
public class Animal : CoreObject, IObjectCopy<Animal>
{
public new Animal Copy()
{
return (Animal) base.Copy();
}
}
Animal copy = myAnimal.Copy();
Another option using bounded quantification:
public class CoreObject : IObjectCopy<CoreObject>
{
public CoreObject Copy()
{
return Copy<CoreObject>();
}
protected T Copy<T>()
where T : CoreObject, new()
{
T t = new T();
//implement copy logic:
return t;
}
}
public class Animal : CoreObject, IObjectCopy<Animal>
{
public new Animal Copy()
{
return Copy<Animal>();
}
}
If I understood it correctly, you need Curiously recurring template pattern
public class BaseClass<T> where T : BaseClass<T>
{
public virtual T Clone()
{
// Perform cloning with reflection.
return clone as T;
}
}
Then you just define your class as:
public class EndObject : BaseClass<EndObject>
{
}
EndObject e;
e.Clone() // Will return EndObject type
Related
public abstract class Base
{
public Base ClassReturn()
{
return this;
}
}
Is there possibility to return child type that invoked ClassReturn method?
I've done that in extension method:
public static T ClassReturn<T>(this T obj) where T : Base
{
return (T) obj.ClassReturn();
}
But I want to embeed it in Base class instead of extension method. Is there possibility to do that with generics?
I will copy my comment which describes what I want to achieve:
I need something similiar to builder pattern and I have different
classes that depending on previous operations do something else, now I
want to have a similiar functionality in every of them and when I use
it I lose object type. So my solution is either implement that
functionality multiple times in every class or create extension
method. But I always thought when it is possible to make extension
method for class then I can embeed that in class, but as I see it is
not possible.
Full example:
public class Child1 : Base
{
public Child1 Operation1()
{
Console.WriteLine("operation1");
return this;
}
}
public class Child2 : Base
{
public Child2 Operation2()
{
Console.WriteLine("operation2");
return this;
}
}
static void Main(string[] args)
{
Child1 ch = new Child1();
ch.Operation1().Operation1().ClassReturn().Operation1()
}
I can't use Operation1 after ClassReturn if I don't use extension method.
Try this one:
public abstract class Base<T> where T: Base<T>
{
public T ClassReturn
{
get { return (T)this; }
}
}
public class Child1 : Base<Child1>
{
}
public class Child2 : Base<Child2>
{
}
From your question and your comments, what you are trying to achieve is not possible directly from the type system. By returning an instance of Base you are specifically saying that all you are interested is that you have something that derives from Base, but that the specific class doesn't matter. Statically, the compiler no longer has the information it needs to perform a cast.
If you are trying to get the original type back statically, then you have to supply the information to the compiler, and in this case you can't guarantee that you have the correct information. In the example below, the instance is created from derived type A but attempted to be cast to derived type B through the extension, the compiler will allow the code to compile, but you'll get an exception at runtime.
public class A : Base { }
public class B : Base { }
public static class BaseExtensions
{
public static T GetAsT<T>(this Base base) where T: Base
{
return (T)base;
}
}
public static void Main()
{
Base obj = new A();
B b = obj.BaseAsT<B>(); // This compiles but causes an exception
}
You should look up the Liscov Substitution Principle to get information on how to properly work with base and derived classes in the system as a whole, and then write up a question dealing specifically with the result you are trying to achieve.
I'm writing an SDK which has an OOP structure for implementing data types;
first an interface
then an abstract implementation
finally an abstract generic implementation
People can choose to implement either the interface, or derive from either of the classes.
public interface IGoo
{
IGoo Duplicate();
...
}
public abstract class Goo : IGoo
{
IGoo IGoo.Duplicate() {
return Duplicate();
}
abstract public Goo Duplicate();
...
}
public abstract class Goo<T> : Goo
{
abstract public Goo<T> Duplicate(); ??????
...
}
I'd like to re-implement the Duplicate method so that it always returns the most specific type possible. I.e. when you call Duplicate on an IGoo instance, you get another IGoo. If you call it on Goo, you get Goo, if you call it on -say- Goo<int>, you get Goo<int>. And all Duplicate() methods always call the most specific implementation.
Is this possible? Is it only possible when you can implement an interface explicitly? In which case, should I not make Goo<int> derive from Goo, but have it implement IGoo instead and type all the low-level functionality twice?
What about the following?
public interface IObj
{
IObj Duplicate();
}
public abstract class Obj : IObj
{
public Obj()
{
}
public virtual IObj Duplicate()
{
return this;
}
}
public abstract class ObjT<T> : Obj
{
public ObjT()
{
}
public override IObj Duplicate()
{
return this;
}
}
public class ObjImpl : Obj
{
}
public class ObjTImpl : ObjT<int>
{
}
I understand that you want it to return the most specific type possible in any inheriting class but it actually is. It's boxing the inheriting type into the interface (or a raw object if you where to return objects instead of interface types. If you run the following test in a console app you will see the proper type is represented:
namespace TestConsole
{
class Program
{
static void Main(string[] args)
{
ObjImpl a = new ObjImpl();
ObjTImpl b = new ObjTImpl();
Console.WriteLine(a.Duplicate().GetType());
Console.WriteLine(b.Duplicate().GetType());
Console.ReadLine();
}
}
}
// outputs:
// ObjImpl
// ObjTImpl
The idea of redefining abstracts of abstracts goes against the purpose of abstract polymorphism. If the derived types do not intend to implement the inherited abstract member, they should not be inheriting it.
Although the example I gave above would require casting to access any child class-specific members, it would be the proper way to do it in this approach. The runtime needs to know what types it should expect to deal with.
There is always dynamics you could play around with but to be honest I haven't played around with dynamics with generics and inheritance as I suspect I would make my compiler cry, and when it cries, I cry, a little bit deep down inside... lol
It is only possible when you implement the interface explicitly. That's because the return type of a method is not part of its signature - which the compiler checks when overloading. Therefore, otherwise identical methods which only differ in their return type are syntactically not possible.
I have a set of classes that derive one from another and the lower level has complete structure of what i need. the data stored and save is the highest level. in the highest level the Type is stored in the object. how can i cast down the highest level to the lowest. the generic see highest and T is highest which isn't helpful.
example :
Head class with couple core methods/fields :
[Serializable()]
public class CSelectionProperties
{
private Dictionary<string, string> lstProperties = new Dictionary<string, string>();
public Dictionary<string, string> getProperties { get { return lstProperties; } }
private Type objectType = null;
public Type ObjectType { get { return objectType; } set { objectType = value; } }
internal string FindProperty(string sProperty)
{
return FindProperty(sProperty, null);
}
internal string FindProperty(string sProperty, string sNullValue)
{
string sValue = sNullValue;
lstProperties.TryGetValue(sProperty, out sValue);
}
}
here an example of one of the many derived class :
[Serializable()]
public class CFilterSelectionProperties : CSelectionProperties, IFilterSelectionProperties
{
public double getAirVolume()
{
return Convert.ToDouble(FindProperty("INCFMValue", "0"));
}
}
Now all object using these property have the variable as CSelectionProperties so we can reuse everywhere same format.
When a class such as CFilterSelectionProperties gets created the Type get stored into the CSelectionProperties.ObjectTypeas a Type now another project receive a collection of CSelectionProperties and to properly read them i need to cast them as the proper type.
Right now i am going the old way
If(item is CFilterSelectionProperties)
{
RunDataAnalysis(item as CFilterSelectionProperties);
}
Else If (item is ...)
{
RunDataAnalysis(item as ...);
}
i use reflection and i stumble upon a case where i need the actual original class to loop the methods and retrieve some data. is there any way ?
Also some report will need to be open but again i have 4 class that derive from 1 single class that derive from CSelectionProperties at which point i don't have access to anything at all. I'm just trying to get away from If/Else which works fine.
As side note i tried going with and Activator but i can only find how to recreate a class as child type.
CFilterSelectionProperties oItem = new CFilterSelectionProperties();
MyObject.SelectionProperties = Activator.CreateInstance(oItem.ObjectType) as CSelectionProperties;
Not exactly sure if this is what you need but you can have a base class that "knows" the derived type:
class MyBase<T> {}
class A : MyBase<A> {}
class B : MyBase<B> {}
this way you can do this:
void Foo(MyBase<T> baseObj)
{
T derived = (T)(object)baseObj;
// use derived in a strongly-typed manner
}
Without knowing what RunDataAnalysis does it sounds like you can use virtual (or abstract) methods/properties in the base class that are overloaded in the derived classes. Then when you call those methods/properties in RunDataAnalysis you will be using the most derived version without having to cast the variable.
For example:
public class CSelectionProperties
{
... existing stuff
public virtual DataSet GetData(.. some parameters ...)
{
.. do stuff common to ALL subtypes
}
}
and
public class CFilterSelectionProperties : CSelectionProperties, IFilterSelectionProperties
{
public override DAtaSet GetData(... some parameters ...)
{
... do stuff common to THIS type and subtypes
}
}
As I've learned that it is not advised to implement ICloneable (due to the fact that it does not differentiate between Deep Copy or Shallow Copy), I'm trying to determine whether I should implement it as an abstract or an interface.
I feel that my implementation would stay largely the same, e.g. a binary deep copy and a MemberwiseClone shallow copy, so to that end I felt that an abstract method would be ideal. However, my understanding is also that C# does not do Multiple Inheritance, thus if I ever need to use another abstract class, then I no longer can.
In that case, I feel that implementing a custom ICloneable (e.g. ICustomCloneable) would be the better option, but if the implementation is effectively the same across many classes, I feel like I'm not adequately taking advantage of code reuse.
That being said, is it valid to use an interface to keep the abstract inheritance clear for more important things in my cloneable classes? Or is there another way to do this?
Alternatively, is it valid (read: not smelly) for an abstract to implement another abstract? This would be my guess as to getting around the single-inheritance that prevents me from implementing the CloneCapable class as well as another abstract, but it sounds like it might be questionable. e.g.:
public abstract class CloneCapable
{
public object ShallowCopy()
{
// implementation
}
public object DeepCopy()
{
// implementation
}
}
public abstract class ClassA : CloneCapable {}
// abstract-abstract since I can't do ClassB : ClassA, CloneCapable
public abstract class ClassB : ClassA {}
I would definitely make this an interface. The reason being is that, interfaces are supposed to be very general, and that's why we can implement multiple interfaces. If there is some boiler-plate code you want to write, there's nothing stopping you taking advantage of both interfaces and abstract classes.
public interface ICustomCloneable<T>
{
T ShallowCopy();
T DeepCopy();
}
public abstract class CustomCloneable<T> ICustomCloneable<T> where T : class
{
public T ShallowCopy() { return ShallowCopy(this); }
public T DeepCopy() { return DeepCopy(this); }
// static helpers
public static object ShallowCopy(T obj) { /* boilerplate implementation */ }
public static object DeepCopy(T obj) { /* boilerplate implementation */ }
}
public class ClassA : CustomCloneable<ClassA> { /* Use boilerplate functionality */ }
public class ClassB : SomeOtherClass, ICustomCloneable<ClassB>
{
// implement ICustomCloneable using static helpers
public ClassB ShallowCopy() { return CustomCloneable<ClassB>.ShallowCopy(this); }
public ClassB DeepCopy() { return CustomCloneable<ClassB>.DeepCopy(this); }
}
I've used generics here, but there's no reason you need to... It might even be desirable not to. This approach allows you to write boilerplate code, but not be tied down by it:
public class ClassC : ICustomCloneable<ClassC>
{
public ClassC ShallowCopy() { /* Do special cloning for ClassC */ }
public ClassC DeepCopy() { /* Do special cloning for ClassC */ }
}
I was thinking that creating an interface was the way to go, but then I found this question and the first answer. That is a fine way to do the cloning, but I thought that that might go very well with a Custom Extension Method so I wrote the fallowing code, based on the code in the first post and on the MS help page:
Some classes to play with:
[Serializable]
public abstract class Base
{
public abstract int m1();
}
[Serializable]
public class derived : Base
{
public int a = 42;
public override int m1()
{
throw new NotImplementedException();
}
}
A class with an extension method based on code samples from both linkes
//Extension methods must be defined in a static class
public static class StringExtension
{
// This is the extension method.
// The first parameter takes the "this" modifier
// and specifies the type for which the method is defined.
public static T MyCloneExtension<T>(this T t)
{
// Code in this function was copied from https://stackoverflow.com/questions/78536/deep-cloning-objects-in-c-sharp
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", "source");
}
// Don't serialize a null object, simply return the default for that object
if (Object.ReferenceEquals(t, null))
{
return default(T);
}
IFormatter formatter = new BinaryFormatter();
Stream stream = new MemoryStream();
using (stream)
{
formatter.Serialize(stream, t);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
}
and finally a call to clone an object
derived d = new derived();
derived d2 = d.MyCloneExtension<derived>();
It is quite puzzling to find out that Generics Constraint Can't Be Casted to Its Derived Type.
Let's say I have the following code:
public abstract class BaseClass
{
public int Version
{ get { return 1; } }
public string FixString { get; set; }
public BaseClass()
{
FixString = "hello";
}
public virtual int GetBaseVersion()
{
return Version;
}
}
public class DeriveClass: BaseClass
{
public new int Version
{ get { return 2; } }
}
And guess what, this method will return a compilation error:
public void FreeConversion<T>(T baseClass)
{
if(baseClass.GetType()==typeof(DeriveClass)
var derivedMe = (DeriveClass)baseClass;
}
I would have to cast the baseClass to object first before I can cast it to DerivedClass, i.e.,
public void FreeConversion<T>(T baseClass)
{
if(baseClass.GetType()==typeof(DeriveClass)
var derivedMe = (DeriveClass)((object)baseClass);
}
Seems to me pretty ugly. Why this is so?
First, you shouldn't be casting a base type variable to a derived type. It's not supposed to work, only the other way around.
Second, why it works via object, is because you remove the compile-time type checks. The compiler can check that a BaseType cannot be cast to DerivedType. But when a variable is object, the compiler leaves it assuming you know what you're doing. Even if it will compile, the code will then crash during execution.
The answer is simple: the compiler can't know that T in your FreeConversion method can be converted to DeriveClass.
As you already stated, the cheap trick is to first cast to object, then to the type you want to go. Ugly, but it works.
Apart from that, it may be that you are violating Liskov Substitution principle, nothing that will harm any animals but can drive your design towards unmaintainable code.
Third, a nice trick to let your base class expose the derived type is something like this:
public class Base<T> where T : Base<T> {
T IAmDerived;
}
public class Derived : Base<Derived> { }
First of all, in your generic method the type T could be a vale type or reference type. And the reason why it allows you to do via 'Object' is that, you're simply doing boxing-unboxing which works for any type in system.
Secondly.it will be a terrible idea to convert/cast a baseclass object into a derived class. You're violating the mechanics of OOP.
If you really want to return an object of type derived from the base class, here's one way possible - the solution is pretty much similar to what Frank has offered.
//This is how you create a function in BaseClass that returns the collection
//of DerivedTypes when called from an object of type derivedclass, no magic just Generics.
//**The BaseClass**
public class BaseClass<T>
where T : BaseClass<T>
{
public HashSet<T> GetHashSet()
{
HashSet<T> _hSet = new HashSet<T>();
//do some work
//create a HashSet<T> and return;
return _hSet;
}
}
//**The Derived Class**
public class DerivedClass : BaseClass<DerivedClass>
{
//you have the method inherited.
}