c# interface in inheritant class [closed] - c#

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
static Eleve[] eleves = new Eleve[6];
static void Main(string[] args)
{
int[] notes;
eleves[0] = new Faineant("Schtroumpf", "Faineant");
eleves[1] = new Fourbe("Schtroumpf", "Fourbe");
eleves[2] = new Bon("Schtroumpf", "Bon");
eleves[3] = new Fayot("Schtroumpf", "Fayot");
eleves[4] = new PasTresBon("Schtroumpf", "PasTrèsBon");
eleves[5] = new PasTresBon("Schtroumpf", "PasTrèsBon 2");
eleves[1].triche(); //Here is the problem ! not swag.
}
*
class Personne
{ public virtual void triche() {}
public virtual void prepareLeCafe() { }
}
*
abstract class Eleve : Personne ;
*
class Tricheur : Eleve, ITricheur
{ void ITricheur.triche()
{
min = 15;
max = 15;
}
}
*
public interface ITricheur
{
void triche();
}
The method called when running "eleves[1].triche() ;" is the one in class Personne and not the one in class Tricheur : Eleve, ITricheur. Can someone explain us our error ? Thanks a lot !

In your case objects in Eleve[] must be of type Tricheur than it will take the implementation you want or all of your other classes (Faineant, Fourbe, ...) have also to implement the same implementation like Tricheur (but last is bad idea).

If Fourbe is a direct child of Eleve
The array you created is of type Eleve.
tatic Eleve[] eleves = new Eleve[6];
Eleve extends Personne and Personne contains a method triche. That is why the Personne.triche is getting called.
The class class Tricheur : Eleve, ITricheur is not actually comes after Eleve. So, there is no point for its triche to get called.
If Fourbe is a direct child of Tricheur
You need to override triche this way,
class Tricheur : Eleve, ITricheur
{
public void override ITricheur.triche()
{
min = 15;
max = 15;
}
}

Seems that you missed out something in your code example. I just added the missing parts from compiler and it works.
The question would now be: Do you like to get into Personne.triche() or into Tricheur.triche()?
internal class Program
{
private static Eleve[] eleves = new Eleve[6];
private static void Main(string[] args)
{
eleves[0] = new Tricheur("Schtroumpf", "Faineant");
eleves[1] = new Tricheur("Schtroumpf", "Fourbe");
eleves[2] = new Tricheur("Schtroumpf", "Bon");
eleves[3] = new Tricheur("Schtroumpf", "Fayot");
eleves[4] = new Tricheur("Schtroumpf", "PasTrèsBon");
eleves[5] = new Tricheur("Schtroumpf", "PasTrèsBon 2");
var eleve = eleves[1];
var tricheur = eleve as ITricheur;
if (tricheur != null)
tricheur.triche();
eleve.triche();
}
}
public interface ITricheur
{
void triche();
}
internal abstract class Eleve : Personne
{ }
internal class Personne
{
public virtual void prepareLeCafe()
{ }
public virtual void triche()
{ }
}
internal class Tricheur : Eleve, ITricheur
{
private int max;
private int min;
public Tricheur(string a, string b)
{
}
void ITricheur.triche()
{
min = 15;
max = 15;
}
}
Update
So to get into Tricheur.triche() you should change your implementation that way:
internal class Tricheur : Eleve, ITricheur
{
public Tricheur(string a, string b)
{
}
void ITricheur.triche()
{
// If you remove this method, you'll get
// always into the overriden method below.
}
public override void triche()
{
}
}

The two methods:
public virtual void triche() {}
and
void ITricheur.triche()
are two different methods. The letter one being an explicit implementation of ITricheur.triche.
In case you really want to create a virtual triche method in the ultimate ancestor, you have to override it in the descendant (regardless it's declared in the interface as well — the two will actually match), like this:
public override void triche() { … }

You have methods with same name at class and interface, by default you call method from Personne(parent) class. If you need call method from ITrecheur you must call
(eleves[1] as ITricheur).triche();

you issue is the following Tricheur inherits from Eleve so your debugger see the triche() as correct but at runtime will not do anything as virtual has no implentation and nothing will be executed
so you should do something like this
public class Personne {
public virtual void triche() { }
public virtual void prepareLeCafe() { }
}
public abstract class Eleve : Personne
{
public override void triche()
{
// here your code
}
}

Related

Using base class and base interface in C#

I am reshaping an entire system that does not use base classes and base interfaces.
My idea to do so is to extract all the common methods to a base classes and base interfaces.
So basically, we would have:
A base class SomeClassBase implementing an interface ISomeClassBase
A derived class SomeClassDerived implementing ISomeClassDerived (this interface deriving from ISomeClassBase)
Now the problem, how can I instantiate "_mySession" in the derived class (which has a different cast than in the base class), while preserving all the methods from the base class:
public class SomeClassBase : ISomeClassBase
{
public IMySessionBase _mySession = MySession.Instance();
public SomeClassBase ()
{
_mySession.connect(); // Needed??
}
public void doSomething()
{
_mySession.doSomething();
}
}
public class SomeClassDerived : SomeClassBase, ISomeClassDerived
{
public IMySessionDerived _mySession = MySession.Instance();
public SomeClassDerived ()
{
_mySession.connect();
}
public void doSomethingElse()
{
_mySession.doSomethingElse();
}
}
One more thing, IMySessionDerived implements IMySessionBase.
Do not redefine _mySession Let it come from base class.
However in you Derived class you can still reassign.
public class SomeClassDerived : SomeClassBase, ISomeClassDerived
{
public SomeClassDerived ()
{
_mySession = MySession.Instance(); //Declaration comes from base class automatically
_mySession.connect();
}
public void doSomethingElse()
{
_mySession.doSomethingElse();
}
}
If your IMySessionBase and IMySessionDerived are following Hierarchy, it should work. But in some rare cases, You might end up getting into a DoubleDispatchProblem.
As Pointed out in commens, If you want to do something from IMySessionDerived you can add a Property.
public class SomeClassDerived : SomeClassBase, ISomeClassDerived
{
IMySessionDerived _derivedSessionAccessor=> _mySession as IMySessionDerived;
}
Update: To fix the exact design problem here,
Instead of deriving from the base class, have it as a field. And inherit from interface. So Instead of doing above approach,
do like,
public class SomeClassBase : ISomeClassBase
{
public IMySessionBase _mySession ;
public SomeClassBase ( IMySessionBase session)
{
_mySession=session;
_mySession.connect(); // Needed??
}
public void doSomething()
{
_mySession.doSomething();
}
}
public class SomeClassDerived : , ISomeClassDerived
{
public IMySessionDerived _mySession = MySession.Instance();
private SomeClassBase _baseClassInstance;
public SomeClassDerived ()
{
_baseClassInstance=new SomeClassBase(_mySession);
//_mySession.connect();
}
public void doSomethingElse()
{
_baseClassInstance.doSomethingElse();
}
}
Pasting #Selvin answer instead of the link buried in the comments:
The trick here is to use the keyword "base()"
using System;
using System.Runtime.CompilerServices;
public class Program
{
public static void Main()
{
var o1 = new O1();
o1.DS1();
var o2 = new O2();
o2.DS1();
o2.DS2();
}
public class Session1
{
protected readonly Type ownerType;
public Session1(Type type)
{
ownerType = type;
}
public virtual void DS1([CallerMemberName] string functionName = "")
{
Console.WriteLine(ownerType.Name + ":" + GetType().Name + ":" + functionName);
}
}
public class Session2 : Session1
{
public Session2(Type type):base(type) { }
public virtual void DS2([CallerMemberName] string functionName = "")
{
Console.WriteLine(ownerType.Name + ":" + GetType().Name + ":" + functionName);
}
}
public class O1
{
private readonly Session1 t;
public O1() : this(new Session1(typeof(O1))) { }
protected O1(Session1 t)
{
this.t = t;
}
public void DS1()
{
t.DS1();
}
}
public class O2 : O1
{
private readonly Session2 t;
public O2() : this(new Session2(typeof(O2))) { }
protected O2(Session2 t) : base(t)
{
this.t = t;
}
public void DS2()
{
t.DS2();
}
}
}

Is this the only way to have the functionality of abstract static methods?

I'm working on a framework right now and the motto is "no redundancy" and "I don't want to know the vendor specifics" so most things are handled through Interfaces and Generic classes. Now I had the situation where I have an abstract class that wants to match things depending on it's own Enum variable se but it shouldn't have to know how the vendor provides a relatable variable to be matched to se. The vendor could have decided an integer, an Enum or a string would be the best to save that information but honestly I don't want to know.
So I thought well no problem have an abstract static method that must be provided by every implementation of a wrapper to compare se with the vendor specific way of saving that information.
//The original version I wanted to be possible
public abstract class AbstractGenericClass<TWrapper<T>, T> where TWrapper : AbstractGenericWrapper<T> {
protected TWrapper tWrapper;
//our SomeEnum se is somehow relatable to every T
//but we don't want to know how
protected SomeEnum se = ...;
//called on Start
public void Start() {
List<T> ts = FindObjectsOfType<T>;
foreach (T t in ts) {
if(T.Compare(t, this.se)) {
tWrapper = new TWrapper(t);
}
}
}
}
public abstract class AbstractGenericWrapper<T> {
T _t;
public AbstractGenericWrapper(T t) {
_t = t;
}
public static abstract bool Compare(T t, SomeEnum someEnum);
}
public class ConcreteNongenericWrapper : AbstractGenericWrapper<VendorSpecificImplementation> {
public static bool Compare(VendorSpecificImplementation t, SomeEnum someEnum) {
return t.vendorVariable.toLower().Equals(Enum.GetValues(typeof(someEnum), someEnum));
}
}
public class OtherConcreteNongenericWrapper : AbstractGenericWrapper<OtherVendorSpecificImplementation> {
public static bool Compare(OtherVendorSpecificImplementation t, SomeEnum someEnum) {
return t.otherVendorVariable % 3 == (int) someEnum;
}
}
public class SomeImplementation {
public static void main() {
AbstractGenericClass<ConcreteNongenericWrapper<ConcreteNongeneric>, ConcreteNongeneric> foo
= new AbstractGenericClass<ConcreteNongenericWrapper<ConcreteNongeneric>, ConcreteNongeneric>();
AbstractGenericClass<OtherConcreteNongenericWrapper<OtherConcreteNongeneric>, OtherConcreteNongeneric> bar
= new AbstractGenericClass<OtherConcreteNongenericWrapper<OtherConcreteNongeneric>, OtherConcreteNongeneric>();
foo.Start();
bar.Start();
}
}
I found out that that isn't possible and I wanted to know if this version down below is the best/only way of doing it? It has redundancy and I don't like it and it is longer.
//An attempt at a solution:
public abstract class AbstractGenericClass<TWrapper<T>, T> where TWrapper : AbstractGenericWrapper<T> {
protected TWrapper tWrapper;
//our SomeEnum se is somehow relatable to every T
//but we don't want to know how
protected SomeEnum se = ...;
//called on start
public abstract void Start();
}
public abstract class AbstractGenericWrapper<T> {
T _t;
public AbstractGenericWrapper(T t) {
_t = t;
}
}
public class ConcreteNongenericClass : AbstractGenericClass<VendorSpecificImplementation> {
//called on start
public override void Start() {
List<VendorSpecificImplementation> ts = FindObjectsOfType<VendorSpecificImplementation>;
foreach (VendorSpecificImplementation t in ts) {
if(t.vendorVariable.toLower().Equals(Enum.GetValues(typeof(someEnum), someEnum))) {
tWrapper = new ConcreteNongenericWrapper(t);
}
}
}
}
public class ConcreteNongenericWrapper : AbstractGenericWrapper<VendorSpecificImplementation> {
}
public class OtherConcreteNongenericClass : AbstractGenericClass<OtherVendorSpecificImplementation> {
//called on start
public void Start() {
List<OtherVendorSpecificImplementation> ts = FindObjectsOfType<OtherVendorSpecificImplementation>;
foreach (OtherVendorSpecificImplementation t in ts) {
if(t.otherVendorVariable % 3 == (int) someEnum) {
tWrapper = new OtherConcreteNongenericWrapper(t);
}
}
}
}
public class OtherConcreteNongenericWrapper : AbstractGenericWrapper<OtherVendorSpecificImplementation> {
}
public class SomeImplementation {
public static void main() {
AbstractGenericClass<ConcreteNongenericWrapper<ConcreteNongeneric>, ConcreteNongeneric> foo
= new AbstractGenericClass<ConcreteNongenericWrapper<ConcreteNongeneric>, ConcreteNongeneric>();
AbstractGenericClass<OtherConcreteNongenericWrapper<OtherConcreteNongeneric>, OtherConcreteNongeneric> bar
= new AbstractGenericClass<OtherConcreteNongenericWrapper<OtherConcreteNongeneric>, OtherConcreteNongeneric>();
foo.Start();
bar.Start();
}
}
Thank you very much for your time and help!

Intelligent Generic Static Method

I wrote C# code as described below that inherits a class from a generic class with static methods. I want to call the child class for its static methods (inherited from the base class) without having to specify the type.
EDITED! More "real" code
public class Rec
{
public string Name { get; set; }
public override string ToString() { return this.Name; }
public virtual void Load() { /* HERE IT READS A TEXT FILE AND LOAD THE NAME */ }
}
public class BaseClass<T> : Rec
{
public T Argument { get; set; }
public override void Load() { /* NOW IT LOADS ALSO THE ARGUMENT */ }
public static H Method<H>() where H : Rec, new()
{
H iH = new H();
iH.Load();
iH.Name += " " + iH.Argument.ToString();
return iH;
}
}
public class Child : BaseClass<string> { }
public class SomeOtherClass
{
public void Test()
{
Child i = Child.Method();
//instead of Child.Method<Child>();
}
}
So, instead of having to call method<h>() i'd like to just call method(), so the code should assume that "h" is the caller type. Like in:
How can I do it?
Static methods are not inherited in C#
See this answer for an idea of a potential implementation: Stack Overflow whats-the-correct-alternative-to-static-method-inheritance
You could change method<h> to method and make it an instance method:
public class BaseClass<T> where T, new()
{
public T method() { /* RETURN SOMETHING */ }
}
And then call it as follows:
public class ABC : Child
{
public void Test()
{
var iABC = this.method();
}
}

Force override method if another method is overriden

Is there a way to force the override of a virtual method if another method is overriden?
public class BaseClass
{
protected virtual void A()
{
// a default action called first
}
protected virtual void B()
{
// a default action called second that,
// if A was overriden, makes no sense
}
}
EDIT
Thanks a lot for the Answers. It's very interresting to see how this could be achieved, but for my explicit case it's not critically important.
Also, i forgot to mention how those Methods would be used: (in BaseClass)
pulbic bool EditEntity(Guid id)
{
A();
// Some code that edits Entites
B();
}
No, you cannot. But this makes me think how could you achieve the same concept?
The best idea I came up with was declaring an interface which had the package of methods to override.
public interface IMyOverridablePackage
{
void A_Override();
void B_Override();
}
Then give the base class a protected method where the child class can explicitly override the set of methods.
protected void SetOverride(IMyOverridablePackage overridablePackage)
{
_overridablePackage = overridablePackage;
}
So then here's two classes, one which does and one which does not override the set of methods:
public class NotOverriding : MyBaseClass
{
}
public sealed class Overriding : MyBaseClass, IMyOverridablePackage
{
public Overriding()
{
SetOverride(this);
}
void IMyOverridablePackage.A_Override()
{
Console.WriteLine("Overriding.A_Override");
}
void IMyOverridablePackage.B_Override()
{
Console.WriteLine("Overriding.B_Override");
}
}
And the implementation of the base class:
public abstract class MyBaseClass
{
private IMyOverridablePackage _overridablePackage;
public void A()
{
_overridablePackage.A_Override();
}
public void B()
{
_overridablePackage.B_Override();
}
private class MyDefaultPackage : IMyOverridablePackage
{
private readonly MyBaseClass _myBaseClass;
internal MyDefaultPackage(MyBaseClass myBaseClass)
{
_myBaseClass = myBaseClass;
}
void IMyOverridablePackage.A_Override()
{
_myBaseClass.A_Impl();
}
void IMyOverridablePackage.B_Override()
{
_myBaseClass.B_Impl();
}
}
protected MyBaseClass()
{
_overridablePackage = new MyDefaultPackage(this);
}
private void A_Impl()
{
Console.WriteLine("MyBaseClass.A_Impl");
}
private void B_Impl()
{
Console.WriteLine("MyBaseClass.B_Impl");
}
protected void SetOverride(IMyOverridablePackage overridablePackage)
{
_overridablePackage = overridablePackage;
}
}
This does achieve the goal, but of course you have to ask 'how much to I want it?' Is it worth the extra code?
Here's a working dotnetfiddle: https://dotnetfiddle.net/xmPn20
Maybe you cannot force it via compiler errors, but you could write a test which asserts that the methods are in sync via some attributes. It would also be visible that there is some dependency.
A crude example would be something like this:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class VersionAttribute : Attribute
{
public VersionAttribute(string version)
{
Version = version;
}
public string Version { get; set; }
}
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class DependentAttribute : Attribute
{
public string DependentOnMethod { get; set; }
public string DependentOnVersion { get; set; }
}
[Dependent(DependentOnMethod = "OtherMethod", DependentOnVersion = "1")]
public static void FirstMethod()
{
}
[Version("1")]
public static void OtherMethod()
{
}
And the test that asserts the version numbers:
[Test]
public void TestVersions()
{
foreach (var type in Assembly.GetExecutingAssembly().GetTypes())
{
foreach (var method in type.GetMethods())
{
foreach (var customAttribute in method.GetCustomAttributes())
{
var dependent = customAttribute as DependentAttribute;
if (dependent != null)
{
var methodInfo = type.GetMethod(dependent.DependentOnMethod);
Assert.That(methodInfo, Is.Not.Null, "Dependent method not found");
VersionAttribute version = methodInfo.GetCustomAttributes().OfType<VersionAttribute>().FirstOrDefault();
Assert.That(version, Is.Not.Null, "No version attribute on dependent method");
Assert.That(dependent.DependentOnVersion, Is.EqualTo(version.Version));
}
}
}
}
}
thus, if you update one of your methods you would need to update the version number of either the Version attribute or the Dependent attribute. Hopefully better than nothing.
You may change your design :
public abstract class BaseClass
{
protected abstract void A();
}
public class BaseClassEx
{
protected sealed override void A()
{
// action Calling B
}
protected virtual void B()
{
// a default action called second
}
}
In the case of Equals (actually both Equals overloads, concrete type and object) and GetHashCode, Resharper includes a rule that shows a warning in its IntelliSense whenever you forget to implement one of these.
You could enforce it in your code with a runtime check in the constructor of the base class:
public class Base
{
public Base()
{
var baseA = typeof (Base).GetRuntimeMethod("MethodA", new Type[0]);
var baseB = typeof (Base).GetRuntimeMethod("MethodB", new Type[0]);
var derivedA = GetType().GetRuntimeMethod("MethodA", new Type[0]);
var derivedB = GetType().GetRuntimeMethod("MethodB", new Type[0]);
if (baseA.DeclaringType == derivedA.DeclaringType ^
baseB.DeclaringType == derivedB.DeclaringType)
throw new InvalidOperationException("You must override MethodA and MethodB together.");
}
public virtual string MethodA() { return "Hello"; }
public virtual int MethodB() { return 123; }
}

Clone derived class from base class method

I have an abstract base class Base which has some common properties, and many derived ones which implement different logic but rarely have additional fields.
public abstract Base
{
protected int field1;
protected int field2;
....
protected Base() { ... }
}
Sometimes I need to clone the derived class. So my guess was, just make a virtual Clone method in my base class and only override it in derived classes that have additional fields, but of course my Base class wouldn't be abstract anymore (which isn't a problem since it only has a protected constructor).
public Base
{
protected int field1;
protected int field2;
....
protected Base() { ... }
public virtual Base Clone() { return new Base(); }
}
public A : Base { }
public B : Base { }
The thing is, since I can't know the type of the derived class in my Base one, wouldn't this lead to have a Base class instance even if I call it on the derived ones ? (a.Clone();) (actually after a test this is what is happening but perhaps my test wasn't well designed that's why I have a doubt about it)
Is there a good way (pattern) to implement a base Clone method that would work as I expect it or do I have to write the same code in every derived class (I'd really like to avoid that...)
Thanks for your help
You can add a copy constructor to your base class:
public abstract Base
{
protected int field1;
protected int field2;
protected Base() { ... }
protected Base(Base copyThis) : this()
{
this.field1 = copyThis.field1;
this.field2 = copyThis.field2;
}
public abstract Base Clone();
}
public Child1 : Base
{
protected int field3;
public Child1 () : base() { ... }
protected Child1 (Child1 copyThis) : base(copyThis)
{
this.field3 = copyThis.field3;
}
public override Base Clone() { return new Child1(this); }
}
public Child2 : Base
{
public Child2 () : base() { ... }
protected Child (Child copyThis) : base(copyThis)
{ }
public override Base Clone() { return new Child2(this); }
}
public Child3 : Base
{
protected int field4;
public Child3 () : base() { ... }
protected Child3 (Child3 copyThis) : base(copyThis)
{
this.field4 = copyThis.field4;
}
public override Base Clone()
{
var result = new Child1(this);
result.field1 = result.field2 - result.field1;
}
}
Just override the Clone and have another method to CreateInstance then do your stuff.
This way you could have only Base class avoiding generics.
public Base
{
protected int field1;
protected int field2;
....
protected Base() { ... }
public virtual Base Clone()
{
var bc = CreateInstanceForClone();
bc.field1 = 1;
bc.field2 = 2;
return bc;
}
protected virtual Base CreateInstanceForClone()
{
return new Base();
}
}
public A : Base
{
protected int fieldInA;
public override Base Clone()
{
var a = (A)base.Clone();
a.fieldInA =5;
return a;
}
protected override Base CreateInstanceForClone()
{
return new A();
}
}
I did something similar as Alexander Simonov, but perhaps simpler. The idea is (as I said in a comment) to have just one Clone() in the base class and leave all the work to a virtual CloneImpl() which each class defines as needed, relying on the CloneImpl()s of the base classes.
Creation of the proper type is left to C#'s MemberwiseClone() which will do whatever it takes for the object that's calling. This also obviates the need for a default constructor in any of the classes (none is ever called).
using System;
namespace CloneImplDemo
{
// dummy data class
class DeepDataT : ICloneable
{
public int i;
public object Clone() { return MemberwiseClone(); }
}
class Base: ICloneable
{
protected virtual Base CloneImpl()
{
// Neat: Creates the type of whatever object is calling.
// Also obviates the need for default constructors
// (Neither Derived1T nor Derived2T have one.)
return (Base)MemberwiseClone();
}
public object Clone()
{
// Calls whatever CloneImpl the
// actual calling type implements.
return CloneImpl();
}
}
// Note: No Clone() re-implementation
class Derived1T : Base
{
public Derived1T(int i) { der1Data.i = i; }
public DeepDataT der1Data = new DeepDataT();
protected override Base CloneImpl()
{
Derived1T cloned = (Derived1T)base.CloneImpl();
cloned.der1Data = (DeepDataT)der1Data.Clone();
return cloned;
}
}
// Note: No Clone() re-implementation.
class Derived2T : Derived1T
{
public Derived2T(int i1, int i2) : base(i1)
{
der2Data.i = i2;
}
public string txt = string.Empty; // copied by MemberwiseClone()
public DeepDataT der2Data = new DeepDataT();
protected override Base CloneImpl()
{
Derived2T cloned = (Derived2T)base.CloneImpl();
// base members have been taken care of in the base impl.
// we only add our own stuff.
cloned.der2Data = (DeepDataT)der2Data.Clone();
return cloned;
}
}
class Program
{
static void Main(string[] args)
{
var obj1 = new Derived2T(1,2);
obj1.txt = "this is obj1";
var obj2 = (Derived2T)obj1.Clone();
obj2.der1Data.i++;
obj2.der2Data.i++; // changes value.
obj2.txt = "this is a deep copy"; // replaces reference.
// the values for i should differ because
// we performed a deep copy of the DeepDataT members.
Console.WriteLine("obj1 txt, i1, i2: " + obj1.txt + ", " + obj1.der1Data.i + ", " + obj1.der2Data.i);
Console.WriteLine("obj2 txt, i1, i2: " + obj2.txt + ", " + obj2.der1Data.i + ", " + obj2.der2Data.i);
}
}
}
Output:
obj1 txt, i1, i2: this is obj1, 1, 2
obj2 txt, i1, i2: this is a deep copy, 2, 3
You could do something like this:
public class Base<T> where T: Base<T>, new()
{
public virtual T Clone()
{
T copy = new T();
copy.Id = this.Id;
return copy;
}
public string Id { get; set; }
}
public class A : Base<A>
{
public override A Clone()
{
A copy = base.Clone();
copy.Name = this.Name;
return copy;
}
public string Name { get; set; }
}
private void Test()
{
A a = new A();
A aCopy = a.Clone();
}
But i doubt that it will bring something useful. I'll create another example..
I got another idea using the Activator class:
public class Base
{
public virtual object Clone()
{
Base copy = (Base)Activator.CreateInstance(this.GetType());
copy.Id = this.Id;
return copy;
}
public string Id { get; set; }
}
public class A : Base
{
public override object Clone()
{
A copy = (A)base.Clone();
copy.Name = this.Name;
return copy;
}
public string Name { get; set; }
}
A a = new A();
A aCopy = (A)a.Clone();
But i would go for the Alexander Simonov answer.
If performance is not important for your case, you can simplify your code by creating just one general clone method which can clone whatever to whatever if properties are same:
Base base = new Base(){...};
Derived derived = XmlClone.CloneToDerived<Base, Derived>(base);
public static class XmlClone
{
public static D CloneToDerived<T, D>(T pattern)
where T : class
{
using (var ms = new MemoryStream())
{
using (XmlWriter writer = XmlWriter.Create(ms))
{
Type typePattern = typeof(T);
Type typeTarget = typeof(D);
XmlSerializer xmlSerializerIn = new XmlSerializer(typePattern);
xmlSerializerIn.Serialize(writer, pattern);
ms.Position = 0;
XmlSerializer xmlSerializerOut = new XmlSerializer(typeTarget, new XmlRootAttribute(typePattern.Name));
D copy = (D)xmlSerializerOut.Deserialize(ms);
return copy;
}
}
}
}
Found this question while trying to solve this exact problem, had some fun with LINQPad while at it.
Proof of concept:
void Main()
{
Person p = new Person() { Name = "Person Name", Dates = new List<System.DateTime>() { DateTime.Now } };
new Manager()
{
Subordinates = 5
}.Apply(p).Dump();
}
public static class Ext
{
public static TResult Apply<TResult, TSource>(this TResult result, TSource source) where TResult: TSource
{
var props = typeof(TSource).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var p in props)
{
p.SetValue(result, p.GetValue(source));
}
return result;
}
}
class Person
{
public string Name { get; set; }
public List<DateTime> Dates { get; set; }
}
class Manager : Person
{
public int Subordinates { get; set; }
}

Categories