Creating an abstract generic method - c#

I have a C# class with a method such as below:
public class MyType
{
public MyType Clone()
{
var clone = (MyType)MemberwiseClone();
// Do some other stuff here with the clone's properties
return clone;
}
}
I have a bunch of other classes where I want to implement the Clone method so I was thinking I could create an abstract base class where I could define the Clone method generically so I don't have to put a concrete implementation in each class.
I would think this is possible but I haven't worked too much with generics and my attempts to do this in the past (months ago, so discarded my code out of frustration) haven't been successful.
Is this possible? If so, how could it be done?

Create an abstract generic base and then implement the concrete type on the derived ones:
public abstract class ClonableBase<T>
{
public T Clone()
{
return (T)this.MemberwiseClone();
}
}
public class RealClass : ClonableBase<RealClass> { }

The usefulness of this approach depends significantly on what it is that you're cloning.
Here's a method that I use. The cloning method is a bit crude. It's specifically for objects that are meant to be serialized as JSON.
That's why the generic constraint (TEntity : BaseEntity) is there. I don't want just anything passed into this method, only something that I know is serializable.
I also avoided using the generic argument for JsonConvert.DeserializeObject because while I want to cast the result as a specific type, I don't want to pass in an inherited type and get back an instance of a base type.
public static TEntity CloneEntity<TEntity>(this BaseEntity input) where TEntity
: BaseEntity
{
if (input == null) return null;
var serialized = JsonConvert.SerializeObject(input);
return (TEntity)JsonConvert.DeserializeObject(serialized, input.GetType());
}
Although it's already been accepted, I don't recommend adding this to a base class unless absolutely necessary. Before long you might find that you need to clone something that already inherits from a different base class.
This requires the Newtonsoft.JSON package.
As mentioned in a comment, this will do a deep clone. As I stated at the top, this method applies only if serialization/deserialization cloning is appropriate to the types you need to clone. If there were a universally applicable way to clone objects that applied in every case then object would probably have a public Clone method.
If we're cloning classes it's likely because they contain data, and where that's the case deep cloning is likely preferable. For example, suppose we have a Customer class, and one if its properties exposes an Address object. MemberwiseClone will clone the value types, but will result in two Customer objects that share a reference to the same Address. If we're cloning it's usually because we're trying to create entirely distinct objects. If we think we've cloned something but beneath the surface the original and clone share object references then there's a good chance we'll have bugs.

Built on #Gusman's solution I add the possibility to do some initialization
public abstract class ClonableBase<T>
{
public T Clone()
{
T clone = (T)MemberwiseClone();
Initialize(clone)
return clone;
}
protected virtual void Initialize(T clone)
{
}
}
If the initialization is mandatory, you can also make Initialize abstract instead.
public class RealClass : ClonableBase<RealClass> {
protected override void Initialize(T clone)
{
// Do some other stuff here with the clone's properties
}
}

Related

Call (static) method from child clases

I've created an abstract class, lets call it FooBarizable, that is the parent of 2 clases(more in the practice), Foo and Bar. Now, I have a FooBarizableManager that manages Foo and Bar classes, depending on his type. And from this FroobarizableManager, I want to call getFooBarizables(). Let's see the structure:
FooBarizable.cs:
public abstract class FooBarizable{
public string Name { get; set; }
public static IEnumerable<FooBarizable> GetFooBars(){
throw new NotImplementedException();
}
}
Foo.cs:
public class Foo : FooBarizable{
public static IEnumerable<FooBarizable> GetFooBars(){
return API.getFoos();
}
}
Bar.cs:
public class Bar : FooBarizable{
public static IEnumerable<FooBarizable> GetFooBars(){
return API.getBars();
}
}
FooBarizableManager.cs:
public class FooBarizableManager {
private Type type;
public FooBarizableManager(Type _t){
this.type = _t;
}
public void showFooBarizables(){
MethodInfo method = type.GetMethod("GetFooBars");
IEnumerable<FooBarizable> FooBars = (IEnumerable<FooBarizable>)method.invoke(null, null);
show(FooBars);
}
...
}
So, my problem is that I want to get the object collection from the manager, using the type, but enforce child classes to implement getFooBars() method.
Problems I've faced:
.Net does not allow to define static abstract methods, so I cannot create public static abstract IEnumerable<FooBarizable> GetFooBars() and enforce child class to implement it.
The way that is implemented does not enforce the implementation of the method in child classes, but I try to at least throw a NotImplementedException. The problem is that when I call MethodInfo method = type.GetMethod("GetFooBars"); in the manager, if the subclase does not implements the method, method is null, and NullPointerExceptionis called instead.
I've tried to create an instance method instead of static a static one, it solves the enforce problem because child classes have to implement it, But it does not seem correct to me to create an unnecessary instance to call a method.
So, is there any solution to enforce child classes to implement getFooBar() method? if not, how can I throw the NotImplementedException instead of NullPointerException?
is there any solution to enforce child classes to implement getFooBar() method?
Not for static methods. Static methods are tied to the specific class, so they can't be inherited, nor abstract or virtual.
If you want to make the method polymorphic it needs to be an instance method.
how can I throw the NotImplementedException instead of NullPointerException
The result you're getting that exception is because the type does not have a GetFooBars method, so method is null. So you could check for null first:
public void showFooBarizables(){
MethodInfo method = type.GetMethod("GetFooBars");
if(method == null)
throw new NotImplementedException();
IEnumerable<FooBarizable> FooBars = (IEnumerable<FooBarizable>)method.invoke(null, null);
show(FooBars);
}
But throwing that exception is a little misleading because it may seem to the caller that the showFooBarizables method is not implemented, not the underlying GetFooBars.
Since these method seem to be factory methods, perhaps you need a factory for each type instead? It seems like you are trying to use generics as a replacement for overloads. Factory methods generally aren't generic since they have to have different logic for each type. You could create a "base" factory that contains common code, then sub-class the factory for each specific type.
Of course .NET doesn't allow you to write virtual static methods :)
The whole point of virtual methods is that when you call the Base.DoSomething method on an instance of type Derived, it's the code in Derived.DoSomething that executes. But that means you need the instance to know its actual runtime type, so that you know what method is really supposed to be executed.
A typical alternative is to use some form of a factory interface. That is, instead of querying Foo.GetFooBars or Bar.GetFooBars, you'll get an instance of a provider of the relevant instance type, e.g. Fooizer.GetFooBars and Barizer.GetFooBars, where both Fooizer and Barizer implement IFooBarProvider. GetFooBars doesn't fit into the FooBarizable interface - because that's not where it belongs. Object-oriented design, responsibility, substitution principles and all that :)
Then, if you need to enforce the implementation in code (e.g. to make sure someone doesn't forget to implement the proper provider), you could make an abstract instance method or property on your type:
public abstract class FooBarizable
{
protected abstract IFooBarProvider GetDefaultProvider();
}
Depending on what you're actually trying to do, it might make sense to make those classes generic. Or not :)
You cannot force child classes to define a static methods. As you noted, abstract methods cannot be static, and interfaces work with instances only. I think you are trying to put too much into a single class. It looks like your trying to create some franken-factory. Instead just separate the factory functionality and the abstract parent object.
public abstract class FooBarizable {
public string Name { get; set; }
}
Factory example:
public static class FooBarizableFactory {
public static IEnumerable<FooBarizable> GetFooBars(Type type){
var parentType = typeof(FooBarizable);
if (!parentType.IsAssignableFrom(type))
throw new ArgumentException("Not a FooBarizable");
switch(type.Name) {
case "Foo":
return new List<Foo>() { new Foo () };
case "Bar":
return new List<Bar>() { new Bar() };
default:
throw new ArgumentException("Not a known FooBarizable");
}
}
}
Usage:
var fooBars = FooBarizableFactory.GetFooBars(typeof(Foo));
Demo of idea.
.Net does not allow to define static abstract methods
Because C# compiler makes static as abstract and sealed. So you can't make it just abstract or sealed.
The problem is that when I call MethodInfo method =
type.GetMethod("GetFooBars"); in the manager, if the subclase does not
implements the method, method is null, and NullPointerExceptionis
called instead.
I said static is abstract and sealed. So because of it's sealed derived class will not have GetFooBars method.
You can use the BindingFlags.FlattenHierarchy flag. That way it will check also protected and public static classes of base classes. If It's not implemented on derived class it will check base class. So in your stiuation base class GetFooBars will called, if the derived one does not have this method.
There's no way to enforce static methods via any form of inheritance or polymorphism, but a potential workaround would be to implement an extension method(s) for FooBarizable, so that any class that inherits it will have access to the extension.
Static methods are not related to the object (instance) of the class, it is always related to the class itself.
One way to enforce the implementation of a method would be the use of an interface.
Another way, and this is what I think you want, since this method will have different behavior in different instances, would be the use of abstract methods.
public abstract class AbstractClass
{
public abstract int MustIMplementThis(string param1);
}
public class ChildClass : AbstractClass
{
public override int MustIMplementThis(string param1)
{
throw new NotImplementedException();
}
}
All classes that inherits from AbstracClass will have to implement the methods listed on the parent class.

How to define virtual method with return type which is not void in C#

This might sound like a dumb question, but I need to write a virtual method that is being overridden by inherited class. I don't need the virtual method to have any code, since this method is fully dependent on inherited class, therefore all code will be in the override methods.
However, the method has a return type that is not void. If I keep the virtual method empty it would give me an error "no all path return a value".
The only solution I came up with was to implement the virtual method with returning a dummy empty string, but I don't feel this is the best way. Is there any other way to define a virtual method with return type?
Edit:
Even most answers were correct in their own way, they did not help in my case, therefore I am adding snippets of the code which shows why I need to create instance of the base class, and why I can't use interface, or abstract:
//base class
public class Parser
{
public virtual string GetTitle()
{
return "";
}
}
//sub class
public class XYZSite : Parser
{
public override string GetTitle()
{
//do something
return title;
}
}
// in my code I am trying to create a dynamic object
Parser siteObj = new Parser();
string site = "xyz";
switch (site)
{
case "abc":
feedUrl = "www.abc.com/rss";
siteObj = new ABCSite();
break;
case "xyz":
feedUrl = "www.xzy.com/rss";
siteObj = new XYZSite();
break;
}
//further work with siteObj, this is why I wanted to initialize it with base class,
//therefore it won't break no matter what inherited class it was
siteObj.GetTitle();
I know the way I cast Parser object to Site object doesn't seem very optimal, but this is the only way it worked for me, so Please feel free to correct any thing you find wrong in my code.
Edit (Solution)
I followed the advice of many of replies by using interface and abstract. However it only worked for me when I changed the base class to abstract along with all its methods, and inherited the base class from the interface, and then inherited the sub classes from the base class. That way only I could make sure that all classes have the same methods, which can help me generate variant object in runtime.
Public interface IParser
{
string GetTitle();
}
Public abstract class Parser : IParser
{
public abstract string GetTitle();
}
Public class XYZ : Parser
{
public string GetTitle();
{
//actual get title code goes here
}
}
//in my web form I declare the object as follows
IParser siteObj = null;
...
//depending on a certain condition I cast the object to specific sub class
siteObj = new XYZ();
...
//only now I can use GetTitle method regardless of type of object
siteObj.GetTitle();
I am giving the credit to CarbineCoder since he was the one who put enough effort to take me the closest to the right solution. Yet I thank everyone for the contribution.
You can throw NotImplementedException instead of returning object:
public virtual object Method()
{
throw new NotImplementedException();
}
But if you are not implementing anything in virtual method you can create abstract instead of virtual:
public abstract object Method();
Edit:
Another option is to create interface for it.
public interface IMethods
{
object Method();
}
And make your classes children of this interface.
you need to use abstract here. The abstract modifier indicates that the thing being modified has a missing or incomplete implementation.
public abstract returntype MethodName();
But as you say, 'since this method is fully dependent on inherited class, therefore all code will be in the override methods', than if you are really going to override the functionality of the method in inherited class, why do you care if the method returns dummy or stuff? (e.g: you can make it virtual and get going)
Edit: as you cannot mark class as abstract, you can use virtual method instead.
public virtual returntype MethodName()
{
.....
return xyz;
}
(just for info: An abstract member is implicitly virtual. and abstract is sort of pure virtual. so you need virtual, instead of pure virtual)
Since other answers have discussed about abstract/virtual implementation, I am suggesting my own version.
There is a contradiction in your requirement.
You want a base class which is not an abstract but it has a method which is not implemented. Don't you think this unimplemented method will make the class incomplete and end up making it an abstract one even though you haven't explicitly said so?
So lets assume your class will never be an abstract class and its perfectly reasonable to have it as a normal class. Does it make sense to remove this method from the class altogether and move it to an interface?
Can you try extracting this method and put it into an interface.
interface NewInterface
{
string NewMethod();
}
public BaseClass
{
...
}
public DerivedClass : BaseClass, NewInterface
{
public string NewMethod
{
...
}
}
If you can do this, then you need not have to worry about the base class being abstract/ having NotImplemented exception, only downside is every derived class should implement this interface, but thats the point of making the base class non-abstract.
I don't see any problem in implementing Abstract BaseClass/ Interface for your approach. Both are supposed to be the solution for your problem.
//Parser siteObj = new Parser(); - Dont initialize it here,
//your are initializing it once more below
NewIterface siteObj;
string site = "xyz";
switch (site)
{
case "abc":
feedUrl = "www.abc.com/rss";
siteObj = new ABCSite();
break;
case "xyz":
feedUrl = "www.xzy.com/rss";
siteObj = new XYZSite();
break;
}

Copying objects to 'this' object in C#

I have a certain hirerchy of classes that needs the capeability to copy all public properties from one object to another.
Each class has a certain set of public properties that might differ from any other class.
Example:
class Base
{
// Common properties/methods...
public void Copy<T>(T data) where T : Base
{
// ...
}
}
class D1 : Base
{
public int ID
{
get;
set;
}
}
class D2 : Base
{
public string Name
{
get;
set;
}
}
Through googling I have read about those methods:
Using reflection
Generating IL code
Serialization
All of them are either very complex or very slow or sometimes both.
Am I missing something? Is there any other way to access the raw this pointer?
EDIT:
I will clerify.
T is of the type of the calling class. For example if it was called by D1 T will always be D1.
The reason for the generic is that I can't really know what T is.
Am I missing something?
Should I just use Base data as the parameter?
What you're missing is that you're asking the compiler to know that T might be one of the types D1 and D2 when all you've said is that T is a Base. How could it possible know what properties or even type your object is as that information is only known at runtime. Even if you could go foreach (PropertyInfo in this.Properties) it's going to find out the name of those properties at runtime so be just as slow as Reflection because how else can it? (it is reflection, just prettier syntax). It can't know what properties are common until it knows what types it's dealing with and you've said "i'm not telling you until runtime" so the answer is "well I'll have to look at runtime" i.e. reflection.
Secondly, just because D1 and D2 might both have a property named Size doesn't mean they are the same property (unless that property is present in a common ancestor).
For example,
ArtilleryAmmo.Shell and
PecanNut.Shell.
AcmeCorp.Staff and GandolfTheWizard.Staff
California.State and MyBrokenEngine.State
LoudSpeaker.Volume and MassiveCrater.Volume
Cave.Bats and BasketballGame.Bats
etc. etc.
You could work around this using an architectural change and use a 'PropertyBag' to store each class' properties.
A PropertyBag is essentially a Dictionary<string, object> where you can give a piece of data a name and add it to the bag. The disadvantage is that everything gets cast to object, so it isn't very type safe plus there's lots of boxing/unboxing, plus the strings as names don't get checked at compile time, so typos are a constant threat.
When you define a property on the class, you store/retrieve the item from the class' propertybag:
public int MyProperty
{
get
{
return (int)_propertyBag["MyProperty"];
}
set
{
if(_propertyBag.Keys.Contains("MyProperty"))
{
_propertyBag["MyProperty"] = value;
}
else
{
_propertyBag.Add("MyProperty", value);
}
}
}
So now to aggregate all the properties of the derived classes, you can expose their 'raw' PropertyBag and iterate through it.
Like I said before, the PropertyBags aren't type-safe, so it you have two classes in the hierarchy with the same property name but different type then you're getting into trouble.
EDIT: If you're concerned with performance, you're going to have to implement this multiple ways and perf test the different implementations -- I can't honestly say if a PropertyBag will actually be faster than using reflection.
The Copy method in the Base class only has access to the properties that are defined in the Base class. You can copy these properties.
But you cannot copy the properties from the subclasses without using something like reflection. But even with reflection you need some kind of knowledge about the mapping of the properties between different subclasses, like copying the ID property to Name.
So you'll need to write separate implementations for each (allowed) subclass conversion.
public interface IBaseCopier<TFrom, TTo> where TFrom : Base, TTo : Base
{
void Copy(TFrom from, TTo to);
}
public class D1ToD2Copier : IBaseCopier<D1, D2>
{
public void Copy(D1 from, D2 to)
{
// Copy properties from the D1 instance to the D2 instance.
}
}
You can register all the ICopier<TFrom, TTo> implementations in a factory class. This class will look up the implementation of the copier, based on the type arguments. If there is no copier for a certain type combination, i.e. the conversion is not supported, the factory should throw an exception.
public class CopierFactory
{
public ICopier<TFrom, TTo> Create<TFrom, TTo>() where TFrom : Base, TTo : Base
{
// Look up the ICopier implementation for the given types.
}
}
Edit
You can use the MemberwiseClone method to create a copy of an object.
public class Base
{
public static T Copy<T>(T data) where T : Base
{
return data.MemberwiseClone() as T;
}
}
If you need more control over the cloning, you can implement the ICloneable interface.
Note: You should realize that you cannot clone a D1 instance into a D2 instance. That would be like cloning a sheep into a horse.
I think the copy method should be inherited by derived classes D1,D2 and their responsibility to copy their own properties to/from other types.
What I would do is create an extension method for the Base class like:
namespace ExtensionMethods
{
public static class MyExtensions
{
public static int CopyTo<T>(this Base source, ref T dest)
{
// Use reflection to cycle public properties and if you find equally named ones, copy them.
}
}
}
Then you could call it in your objects and like:
source.CopyTo<ClassType>(ref this);
I didn't test, so not sure if it would work exactly like described. I did something similar to Cast DataRows into Entities in a big project I worked on.

List with different types

I'm new at the C# thing.... (.net 3.5)
I want a Dictionary to hold two different types of object, one of the type is generic. while iterating through the list, i will call methods like add and clone.
I have tried it with a base class and subclasses....
namespace ConsoleApplication1 {
class Element{
}
class Child1 : Element {
public Child1 Clone() { return clone; }
}
class Child2<T> : Element {
public Child2<T> Clone() { return clone; }
}
class Program {
static void Main(string[] args) {
Dictionary<string, Element> d = new Dictionary<string, Element>();
d.Add("c1", new Child1());
d.Add("c2s", new Child2<string>());
d.Add("c2i", new Child2<int>());
foreach (KeyValuePair<string, Element> kvp in d) {
Element e = kvp.Value.Clone();
}
}
}
}
Is there a way or solution for my needs?
Thanks!
Anna
You could make Clone either abstract or virtual on the base-type (Element), and override it in the derived types, but you can't change the return type when overriding, so it would have to be Element (nothing more specific). You can redeclare methods (new...), but that gets messy, and you can't override and new a method by the same name/signature in the same type.
But if you're happy for the return type to be Element...
abstract class Element{
public abstract Element Clone();
}
class Child1 : Element {
public override Element Clone() { return /* your code */; }
}
class Child2<T> : Element {
public override Element Clone() { return /* your code */; }
}
Since the type of .Value you get out of your dictionary is Element, you need to make sure Element defines all operations it should have, like your Clone method.
I would:
Make Clone virtual, and add it to Element (or make Element abstract, and Clone abstract instead of virtual)
Override Clone in both Child1 and Child2
This way, the code kvp.Value.Clone() would call the right Clone method depending on the object returned from the dictionary.
Don't create a class hierarchy just for the sake of being able to add different objects to one dictionary though.
If the classes don't have a decent enough hierarchical relationship, you would be better off using an interface like ICloneable, which is already available in the .NET framework.
Then, simply instantiate your Dictionary like:
Dictionary<string, ICloneable> d = new Dictionary<string, ICloneable>();
It's more flexible. Creating a hierarchy for the sake of the commonality of being able to perform Clone(), is not the right solution IMO.
Though I agree with Wim, that implementing ICloneable is probably the better solution, rather than trying to enforce a non-existing class hierachy, please be aware that ICloneable is considered a "bad API" as it does not specify whether it uses shallow- or deepcopy semantics (see for instance http://pro-thoughts.blogspot.com/2009/02/write-deep-clone-forget-about.html or do a google search for "ICloneable C# bad API"

Why no ICloneable<T>?

Is there a particular reason why a generic ICloneable<T> does not exist?
It would be much more comfortable, if I would not need to cast it everytime I clone something.
In addition to Andrey's reply (which I agree with, +1) - when ICloneable is done, you can also choose explicit implementation to make the public Clone() return a typed object:
public Foo Clone() { /* your code */ }
object ICloneable.Clone() {return Clone();}
Of course there is a second issue with a generic ICloneable<T> - inheritance.
If I have:
public class Foo {}
public class Bar : Foo {}
And I implemented ICloneable<T>, then do I implement ICloneable<Foo>? ICloneable<Bar>? You quickly start implementing a lot of identical interfaces...
Compare to a cast... and is it really so bad?
ICloneable is considered a bad API now, since it does not specify whether the result is a deep or a shallow copy. I think this is why they do not improve this interface.
You can probably do a typed cloning extension method, but I think it would require a different name since extension methods have less priority than original ones.
I need to ask, what exactly would you do with the interface other than implement it? Interfaces are typically only useful when you cast to it (ie does this class support 'IBar'), or have parameters or setters that take it (ie i take an 'IBar'). With ICloneable - we went through the entire Framework and failed to find a single usage anywhere that was something other than an implementation of it. We've also failed to find any usage in the 'real world' that also does something other than implement it (in the ~60,000 apps that we have access to).
Now if you would just like to enforce a pattern that you want your 'cloneable' objects to implement, that's a completely fine usage - and go ahead. You can also decide on exactly what "cloning" means to you (ie deep or shallow). However, in that case, there's no need for us (the BCL) to define it. We only define abstractions in the BCL when there is a need to exchange instances typed as that abstraction between unrelated libraries.
David Kean (BCL Team)
I think the question "why" is needless. There is a lot of interfaces/classes/etc... which is very usefull, but is not part of .NET Frameworku base library.
But, mainly you can do it yourself.
public interface ICloneable<T> : ICloneable {
new T Clone();
}
public abstract class CloneableBase<T> : ICloneable<T> where T : CloneableBase<T> {
public abstract T Clone();
object ICloneable.Clone() => return this.Clone();
}
public abstract class CloneableExBase<T> : CloneableBase<T> where T : CloneableExBase<T> {
protected abstract T CreateClone();
protected abstract void FillClone(T clone);
public override T Clone() {
T clone = this.CreateClone();
if (clone is null ) {
throw new NullReferenceException( "Clone was not created." );
}
this.FillClone(clone);
return clone
}
}
public abstract class PersonBase<T> : CloneableExBase<T> where T : PersonBase<T> {
public string Name { get; set; }
protected override void FillClone( T clone ) {
clone.Name = this.Name;
}
}
public sealed class Person : PersonBase<Person> {
protected override Person CreateClone() => return new Person();
}
public abstract class EmployeeBase<T> : PersonBase<T> where T : EmployeeBase<T> {
public string Department { get; set; }
protected override void FillClone(T clone) {
base.FillClone(clone);
clone.Department = this.Department;
}
}
public sealed class Employee : EmployeeBase<Employee> {
protected override Employee CreateClone() => return new Employee();
}
It's pretty easy to write the interface yourself if you need it:
public interface ICloneable<T> : ICloneable
where T : ICloneable<T>
{
new T Clone();
}
Having read recently the article Why Copying an Object is a terrible thing to do?, I think this question needs additional clafirication. Other answers here provide good advices, but still the answer isn't complete - why no ICloneable<T>?
Usage
So, you have a class that implements it. While previously you had a method that wanted ICloneable, it now has to be generic to accept ICloneable<T>. You would need to edit it.
Then, you could have got a method that checks if an object is ICloneable. What now? You can't do is ICloneable<> and as you don't know the type of the object at compile-type, you can't make the method generic. First real problem.
So you need to have both ICloneable<T> and ICloneable, the former implementing the latter. Thus an implementer would need to implement both methods - object Clone() and T Clone(). No, thanks, we already have enough fun with IEnumerable.
As already pointed out, there is also the complexity of inheritance. While covariance may seem to solve this problem, a derived type needs to implement ICloneable<T> of its own type, but there is already a method with the same signature (= parameters, basically) - the Clone() of the base class. Making your new clone method interface explicit is pointless, you will lose the advantage you sought when creating ICloneable<T>. So add the new keyword. But don't forget that you would also need to override the base class' Clone() (the implementation has to remain uniform for all derived classes, i.e. to return the same object from every clone method, so the base clone method has to be virtual)! But, unfortunately, you can't both override and new methods with the same signature. Choosing the first keyword, you'd lose the goal you wanted to have when adding ICloneable<T>. Chossing the second one, you'd break the interface itself, making methods that should do the same return different objects.
Point
You want ICloneable<T> for comfort, but comfort is not what interfaces are designed for, their meaning is (in general OOP) to unify the behavior of objects (although in C#, it is limited to unifying the outer behavior, e.g. the methods and properties, not their workings).
If the first reason hasn't convinced you yet, you could object that ICloneable<T> could also work restrictively, to limit the type returned from the clone method. However, nasty programmer can implement ICloneable<T> where T is not the type that is implementing it. So, to achieve your restriction, you can add a nice constraint to the generic parameter:
public interface ICloneable<T> : ICloneable where T : ICloneable<T>
Certainly more restrictive that the one without where, you still can't restrict that T is the type that is implementing the interface (you can derive from ICloneable<T> of different type that implements it).
You see, even this purpose couldn't be achieved (the original ICloneable also fails at this, no interface can truly limit the behavior of the implementing class).
As you can see, this proves making the generic interface is both hard to fully implement and also really unneeded and useless.
But back to the question, what you really seek is to have comfort when cloning an object. There are two ways to do it:
Additional methods
public class Base : ICloneable
{
public Base Clone()
{
return this.CloneImpl() as Base;
}
object ICloneable.Clone()
{
return this.CloneImpl();
}
protected virtual object CloneImpl()
{
return new Base();
}
}
public class Derived : Base
{
public new Derived Clone()
{
return this.CloneImpl() as Derived;
}
protected override object CloneImpl()
{
return new Derived();
}
}
This solution provides both comfort and intended behavior to users, but it's also too long to implement. If we didn't want to have the "comfortable" method returning the current type, it is much more easy to have just public virtual object Clone().
So let's see the "ultimate" solution - what in C# is really intented to give us comfort? Extension methods!
public class Base : ICloneable
{
public virtual object Clone()
{
return new Base();
}
}
public class Derived : Base
{
public override object Clone()
{
return new Derived();
}
}
public static T Copy<T>(this T obj) where T : class, ICloneable
{
return obj.Clone() as T;
}
It's named Copy not to collide with the current Clone methods (compiler prefers the type's own declared methods over extension ones). The class constraint is there for speed (doesn't require null check etc.).
I hope this clarifies the reason why not to make ICloneable<T>. However, it is recommended not to implement ICloneable at all.
A big problem is that they could not restrict T to be the same class. Fore example what would prevent you from doing this:
interface IClonable<T>
{
T Clone();
}
class Dog : IClonable<JackRabbit>
{
//not what you would expect, but possible
JackRabbit Clone()
{
return new JackRabbit();
}
}
They need a parameter restriction like:
interfact IClonable<T> where T : implementing_type
It's a very good question... You could make your own, though:
interface ICloneable<T> : ICloneable
{
new T Clone ( );
}
Andrey says it's considered a bad API, but i have not heard anything about this interface becoming deprecated. And that would break tons of interfaces...
The Clone method should perform a shallow copy.
If the object also provides deep copy, an overloaded Clone ( bool deep ) can be used.
EDIT: Pattern i use for "cloning" an object, is passing a prototype in the constructor.
class C
{
public C ( C prototype )
{
...
}
}
This removes any potential redundant code implementation situations.
BTW, talking about the limitations of ICloneable, isn't it really up to the object itself to decide whether a shallow clone or deep clone, or even a partly shallow/partly deep clone, should be performed? Should we really care, as long as the object works as intended? In some occasions, a good Clone implementation might very well include both shallow and deep cloning.

Categories

Resources