Here is some code for the discussion
abstract class ClassA
{
public abstract void StartProcess();
}
class ClassB : ClassA
{
public override void StartProcess()
{
Console.WriteLine("ClassB: Render");
}
}
class ClassC : ClassA
{
public override void StartProcess()
{
base.StartProcess();//This is where the compiler complains
Console.WriteLine("ClassC: Render");
}
}
Before everyone jumps down my throat, let me just say that I'm fully aware of the why it does not. But there are cases where being able to do so would make sense and prevent having to declare the base class's method as virtual but with an empty implementation.
Coming from Delphi background, we could do this in Delphi and used it in our class design. If you made the mistake of calling the abstract method on the base class (at run time) you've got an "Abstract Error".
Then I wished the (Delphi) complier check me before!
Now I wish the (C#) complier would let me do this!
How weird is that?
The Questions:
Could not the complier/Jitter simply ignore such a call and issue a warning instead of error?
Do others see/feel this pain?
The case I have, where I need this is the following:
ClassA is part of a library (no control over this class)
ClassC is generated (kind of like how an ASP.NET page gets compiled or a Razor View gets compiled.
But a user of the library can define a ClassB and then ClassC will descend from ClassB instead of ClassA (when it gets generated). Similar to how ASP.NET pages normally descend from System.Web.UI.Page but if you've defined your own "base" page and other pages in your app now descendant from your base page then the generated class descends from your base page (which is turn descends from System.Web.UI.Page).
I hope that part is clear. Then looking at the code I've presented, I can't get instances of ClassC to call into the implementation of ClassB because the code gen doesn't know to include base.StartProcess().
EDIT
It seem that some people didn't quite get what I've written. So let's say you were writing the code generation part that generates ClassC that descends from ClassA. Well, since the method is anstract (in ClassA) you can't generate the line of code that calls into StartProcess() (because the complier won't allow it). As a result, if anyone define a ClassB, the code generation still won't call base.StartProcess(). This is in fact what happens in ASP.NET MVC views.
Ideally I'd like the compiler to ignore it. It ignore many things like calling dispose on a null reference for example.
I'm trying to have a discussion rather be preached to...
EDIT2
Let's assume we have a hierarchy as shown in the code above and it worked.
The opportunity we have now is that the base class, ClassA could have an implementation (in the future) for StartProcess() descendants would call into it. The only way to do this today is to define the method virtual with no body. But that feels a bit icky to me.
How could it possibly make sense to call base.StartProcess() when that's been declared to be abstract? There can't possibly be an implementation to call, so the compiler prohibits it.
Personally I like seeing errors at compile-time instead of either seeing an error at execution time or making the JITter ignore a call which I've specifically made. What if it returned a value which you assigned to a variable? What should that variable value be if the method doesn't exist?
If ClassC is going to derive from ClassB, then you won't get the problem - because you won't be calling into an abstract base method. But your code declares that it derives directly from ClassA instead, not ClassB. If ClassC is generated, it should be generated to derive from ClassB instead, which would be fine.
Personally I think the compiler is doing exactly the right thing here.
EDIT: Just to make it absolutely clear what I believe the appropriate solutions are:
If you want to be able to call base.M() from any derived class, you should make it a virtual method with a no-op implementation, instead of an abstract method.
If you have a code generator which should generate a call to base.M() only in the situations where it's generating a class whose base class has an implementation of M, then it's up to the code generator to get that right - the language shouldn't make everyone else suffer (by deferring error reporting to execution time, or worse still swallowing that error by simply performing a no-op) just because one tool has been written incorrectly.
I think the downsides of either making it an execution-time error to call an abstract base method or making it a no-op are worse than the issues described in the question.
Now an interesting language feature which could potentially be useful here would be the idea of a virtual method which forced overrides to call the base implementation either before or after the override... in a similar way to how a constructor in a derived class always has to call a constructor in the base class either directly or via another constructor. I strongly suspect that the complexity of such a feature (what would happen to the return value? How would use specify before/after semantics? What about exceptions?) would outweigh the benefits. In simple class hierarchies, the template method pattern can perform the same duty in a simpler way.
I don't think it would make sense to let the compiler compile such code.
On the other side I understand the situation in which you are. The fix should be made on the code generator: it should not generate calls to abstract methods (can be checked using reflection). If you do not have access to the code of the code generator I am afraid you do not have many options...
You could create a facade object that is derived from A but implements all abstract methods as empty virtual ones and manipulate the code generator to use it instead of A.
I see what you mean. Sometimes it might be convenient to just don't care whether a base class method is abstract or not. But, a subclass is already very coupled to its parent class, so much that the compiler knows exactly what calls are valid and issues error messages accordingly. There're no virtual base classes.
What you can do is define an adapter class. Kind of a no-op that will just implement the abstract methods to do nothing. It might not be feasible if they return values and you can't decide what default value to return. You would now derive from the adapter and call its non-abstract methods.
UPDATE
You can solve your "requirement" by using reflection. Instead of this:
base.StartProcess();
You'd use something like this:
this.BaseCall("StartProcess");
This would call StartProcess on your base class only if it's not abstract.
Here's the ugly code to make it work (which also considers parameters and default return values):
public static class BaseExtensions {
public static void BaseCall(this object self, string methodName, params object[] parameters) {
self.BaseCall(methodName, typeof(void), null, parameters);
}
public static T BaseCallWithReturn<T>(this object self, string methodName, T defaultReturn = default(T), params object[] parameters) {
return (T)self.BaseCall(methodName, typeof(T), defaultReturn, parameters);
}
private static object BaseCall(this object self, string methodName, Type returnType, object defaultReturn, object[] parameters) {
var parameterTypes = parameters.Select(p => p.GetType()).ToArray();
if (self.GetType().BaseType == null) return null;
var method = self.GetType().BaseType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, parameterTypes, null);
if (method == null || method.IsAbstract) return defaultReturn;
var dm = new DynamicMethod(methodName, returnType, new Type[] { self.GetType() }.Concat(parameterTypes).ToArray(), self.GetType());
var il = dm.GetILGenerator();
PushParameters(il, parameterTypes.Length);
il.Emit(OpCodes.Call, method);
il.Emit(OpCodes.Ret);
return dm.Invoke(null, new object[] { self }.Concat(parameters).ToArray());
}
private static void PushParameters(ILGenerator il, int n) {
il.Emit(OpCodes.Ldarg_0);
for (int i = 0; i < n; ++i) {
switch (i+1) {
case 1: il.Emit(OpCodes.Ldarg_1); break;
case 2: il.Emit(OpCodes.Ldarg_2); break;
case 3: il.Emit(OpCodes.Ldarg_3); break;
default: il.Emit(OpCodes.Ldarg_S, i+1); break;
}
}
}
}
Is it worth it? I'll let you decide.
You are deriving ClassC from ClassA, what would you expect base.StartProcess to actually do?
Do you really mean to derive from ClassB
Related
Does anyone have a better way to do the following:
typeof(Service).GetMethod("UpdateData")
.MakeGenericMethod(dataType)
.Invoke(_myService, new object[]{ editData, metaData });
I'd love to do something like:
_myService.UpdateData<dataType>(editData, metaData);
But the <> accessor for generics will not take Type objects. I'm looking for a helper, utility, accessor, or something to make those generic method calls with reflection less cumbersome or at least centralized.
More Specific Example
public class UserService : IUserService
{
async Task<User> UpdateUser<T>(User user, JsonPatchDocument<T> patch){ //do code }
}
Type dtoType = MagicService.getDynamicDtoType();
Type patchType = typeof(JsonPatchDocument<>).MakeGenericType(dtoType);
dynamic patchDoc = _mapper.Map(patch, typeof(JsonPatchDocument<User>), patchType);
User updateUser = await (Task<User>)typeof(UserService).GetMethod("UpdateUser").MakeGenericMethod(dtoType).Invoke(_userService, new object[]{user, patchDoc})
This actually ends up with two issues. One, the dynamic patchDoc isn't the right type to be used in UpdateUser, which I have a separate question in Stackoverflow about (but you can use duck typing here), and the messy calling of that generic method call with reflection. I'm trying to solve both, but for this question I want to clean up the call. If you have ideas on the other piece, which is really a separate issue:
Declaring a type in C# with a Type instance
This answer does not use reflection, but may make your code easier to work with in some circumstances.
We could have a class like this:
public class MyService
{
public void UpdateData<T>(Something data, Something otherData)
{
// do stuff
}
}
Later we find that we have to call it using a Type variable instead of a generic argument, which could mean using reflection. Sometimes it's easier to add a non-generic overload to the original class, and call it from the generic method:
public class MyService
{
public void UpdateData(Type dataType, Something data, Something otherData)
{
// do stuff
}
public void UpdateData<T>(Something data, Something otherData)
{
UpdateData(typeof(T), data, otherData);
}
}
We lose the ability to easily impose constraints on the Type argument like we could with the generic method. We can add validation if we need it.
That gets you as close as possible to the code you're trying to write:
_myService.UpdateData(dataType, editData, metaData);
That's assuming that you find yourself still needing the generic methods at all. If you add non-generic overloads and discover that you're not calling the generic ones anymore, you can just delete them.
A significant benefit of this over reflection is that you can identify where your code is called. A method that's only called using reflection will appear unused.
I'm trying add the ability to lookup elements in a List<KeyValuePair<string,int>> by overriding the indexer.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
public class MyList : List<KeyValuePair<string, int>>
{
public int this[string key]
{
get
{
return base.Single(item => item.Key == key).Value;
}
}
}
}
For some reason, the compiler is throwing this error:
'System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<string,int>>' does not contain a definition for 'Single'.
While it is true that List<T> doesn't have that method, it should be visible because it is an extension method from the System.Linq namespace (which is included). Obviously using this.Single resolves the issue, but why is access via base an error?
Section 7.6.8 of the C# spec says
When base.I occurs in a class or struct, I must denote a member of the base class of that class or struct.
Which might seem to preclude access to extension method via base. However it also says
At binding-time, base-access expressions of the form base.I and base[E] are evaluated exactly as if they were written ((B)this).I and ((B)this)[E], where B is the base class of the class or struct in which the construct occurs. Thus, base.I and base[E] correspond to this.I and this[E], except this is viewed as an instance of the base class.
If base.I is just like ((B)this).I then it seems like extension methods should be allowed here.
Can anyone explain the apparent contradiction in these two statements?
Consider this situation:
public class Base
{
public void BaseMethod()
{
}
}
public class Sub : Base
{
public void SubMethod()
{
}
}
public static class Extensions
{
public static void ExtensionMethod(this Base #base) { }
}
Here are some interesting assertions about this code:
I cannot call the extension method using ExtensionMethod() from neither Base nor Sub.
I cannot call base.ExtensionMethod() from Sub.
I can call the extension method using Extensions.ExtensionMethod(this) from both Sub and Base.
I can call the extension method using this.ExtensionMethod() from both Sub and Base.
Why is this?
I don't have a conclusive answer, partly because there might not be one: as you can read in this thread, you have to add this. if you want to call it in the extension method style.
When you're trying to use an extension method from the type it is in (or - consequently - from a type that is derived from the type used in the extension method), the compiler doesn't realize this and will try to call it as a static method without any arguments.
As the answer states: they [the language designers] felt it was not an important use case scenario to support implicit extension methods (to give the beast a name) from within the type because it would encourage extension methods that really should be instance methods and it was considered plain unnecessary.
Now, it is hard to find out what is happening exactly under the covers but from some playing around we can deduce that base.X() does not help us. I can only assume that base.X performs its virtual call as X() and not this.X() from the context of the baseclass.
What do I do when I want to call the extension method of a baseclass from a subclass?
Frankly, I haven't found any truly elegant solution. Consider this scenario:
public class Base
{
protected void BaseMethod()
{
this.ExtensionMethod();
}
}
public class Sub : Base
{
public void SubMethod()
{
// What comes here?
}
}
public static class Extensions
{
public static void ExtensionMethod(this Base #base)
{
Console.WriteLine ("base");
}
public static void ExtensionMethod(this Sub sub)
{
Console.WriteLine ("sub");
}
}
There are 3 ways (leaving aside reflection) to call the ExtensionMethod(Base) overload:
Calling BaseMethod() which forms a proxy between the subclass and the extensionmethod.
You can use BaseMethod(), base.BaseMethod() and this.BaseMethod() for this since now you're just dealing with a normal instance method which in its turn will invoke the extension method. This is a fairly okay solution since you're not polluting the public API but you also have to provide a separate method to do something that should have been accessible in the context in the first place.
Using the extension method as a static method
You can also use the primitive way of writing an extension method by skipping the syntactic sugar and going straight to what it will be compiled as. Now you can pass in a parameter so the compiler doesn't get all confused. Obviously we'll pass a casted version of the current instance so we're targetting the correct overload:
Extensions.ExtensionMethod((Base) this);
Use the - what should be identical translation - of base.ExtensionMethod()
This is inspired by #Mike z's remark about the language spec which says the following:
At binding-time, base-access expressions of the form base.I and base[E] are evaluated exactly as if they were written ((B)this).I and ((B)this)[E], where B is the base class of the class or struct in which the construct occurs. Thus, base.I and base[E] correspond to this.I and this[E], except this is viewed as an instance of the base class.
The spec literally says that base.I will be invoked as ((B) this).I. However in our situation, base.ExtensionMethod(); will throw a compilation error while ((Base) this).ExtensionMethod(); will work perfectly.
It looks like something is wrong either in the documentation or in the compiler but that conclusion should be drawn by someone with deeper knowledge in the matter (paging Dr. Lippert).
Isn't this confusing?
Yes, I would say it is. It kind of feels like a black hole within the C# spec: practically everything works flawlessly but then suddenly you have to jump through some hoops because the compiler doesn't know to inject the current instance in the method call in this scenario.
In fact, intellisense is confused about this situation as well:
We have already determined that that call can never work, yet intellisense believes it might. Also notice how it adds "using PortableClassLibrary" behind the name, indicating that a using directive will be added. This is impossible because the current namespace is in fact PortableClassLibrary. But of course when you actually add that method call:
and everything doesn't work as expected.
Perhaps a conclusion?
The main conclusion is simple: it would have been nice if this niche usage of extension methods would be supported. The main argument for not implementing it was because it would encourage people to write extension methods instead of instance methods.
The obvious problem here is of course that you might not always have access to the base class which makes extension methods a must but by the current implementation it is not possible.
Or, as we've seen, not possibly with the cute syntax.
Try to cast the instance to its base class:
((BaseClass)this).ExtensionMethod()
Applied to your code:
public class Base
{
public void BaseMethod()
{
}
}
public static class BaseExtensions
{
public static void ExtensionMethod(this Base baseObj) { }
}
public class Sub : Base
{
public void SubMethod()
{
( (Base) this).ExtensionMethod();
}
}
I suspect the answer is no, but I want to know if it is possible to do something like this:
public class MyGenericClass<TSomeClass> {
public void MyGenericMethod<TSomeInterface>()
// This doesn't compile.
where TSomeClass : TSomeInterface
{
//...
}
}
What I mean to indicate in the above (non-working) example is to constrain TSomeInterface such that it can be any base class, implemented interface, or (if you really want to get fancy) implicit conversion of MyGenericClass.
NOTE:
I suspect that the reason why this was never implemented in C# is that generic constraints are not really meant to be code contracts, which is how I am trying to use them here. I really don't care what type TSomeInterface is, so long as it is implemented by TSomeClass.
So far, I have hacked this together:
public class MyGenericClass<TSomeClass> {
public void MyGenericMethod<TIntermediateType, TSomeInterface>()
where TIntermediateType : TSomeClass, TSomeInterface
{
//...
}
}
This more or less enforces the constraint that I want (that TSomeClass must inherit from, or in the case of an interface, implement, TSomeInterface), but calling it is very clumsy, because I have to specify TIntermediateType (even though I really want it to evaluate against TSomeClass):
var myGenericInstance = new MyGenericClass<TSomeClass>();
myGenericInstance.MyGenericMethod(TSomeClass, TSomeInterface);
Additionally, the above hack is broken because a caller could in theory specify a subclass of TSomeClass as the first type parameter, where only the subclass implements TSomeInterface.
The reason that I want to do this is that I am writing a fluent factory pattern for a WCF service, and I would like to prevent the caller (at compile time) from trying to create an endpoint with a contract that the service class doesn't implement. I can obviously check this at runtime (WCF in fact does this for me), but I am a big fan of compile-time checking.
Is there a better/more elegant way to achieve what I am after here?
The way I was able to wrap my head around the reason why this doesn't compile is the following:
Consider this program compiles:
class Program {
class Class1 { }
class Class2 { }
public class MyGenericClass<TSomeClass> {
public void MyGenericMethod<TSomeInterface>() where TSomeClass : TSomeInterface {
}
}
static void Main(string[] args) {
var inst = new MyGenericClass<Class1>();
}
}
Everything is good. The compiler is happy. Now consider I change the Main method:
static void Main(string[] args) {
var inst = new MyGenericClass<Class1>();
inst.MyGenericMethod<Class2>();
}
The compiler will complain that Class1 does not implement Class2. But which line is wrong? The constraint is on the call to MyGenericMethod, but the offending line of code is the creation of MyGenericClass.
In other words, which one gets the red squiggly line?
As discussed in this linked question, you can't use a type parameter that isn't from the current declaration, on the left side of a where clause.
So as suggested by w0lf in that other question, what you can do is provide both types in your interface (rather than method) declaration:
public class MyGenericClass<TSomeClass, TSomeInterface> {
where TSomeClass : TSomeInterface
public void MyGenericMethod() // not so generic anymore :(
{
//...
}
}
That, however, greatly limits your MyGenericMethod and forces your class to declare before-hand what base interface you with to allow.
So another option is to use a static method with more type parameters:
public class MyGenericClass<TSomeClass> {
public static void MyGenericMethod<TSomeClass, TSomeInterface>
(MyGenericClass<TSomeClass> that)
where TSomeClass : TSomeInterface
{
// use "that" instead of this
}
}
Possibly you could make it an extension method to make it appear to the user like an actual method.
Neither of these is exactly what you wanted, but probably better than the intermediate type solution.
As for the reason for why not?, my guess is that it would complicate the compiler without adding enough value. Here's a discussion by Angelika Langer of the same subject but about Java. Although there are significant differences between C# and Java, I think her conclusion might apply here as well:
The bottom line is that the usefulness of lower bounds on type
parameters is somewhat debatable. They would be confusing and perhaps
even misleading when used as type parameters of a generic class. On
the other hand, generic methods would occasionally profit from a type
parameter with a lower bound. For methods, a work-around for the
lack of a lower bound type parameter can often be found. Such a
work-around typically involves a static generic method or a lower
bound wildcard.
She also gives a nice use case, see the link above.
An extension method provides the best solution, though it doesn't totally solve all your concerns.
public class MyGenericClass<TSomeClass>
{
}
public static class MyGenericClassExtensions
{
public static void MyGenericMethod<TSomeClass, TSomeInterface>(this MyGenericClass<TSomeClass> self)
where TSomeClass : TSomeInterface
{
//...
}
}
It is still necessary to specify both types when calling MyGenericMethod, but it prevents the caller from specifying an incorrect type for TSomeClass as is possible with the approach you came up with. With this approach, the method can be called like so:
var myGenericInstance = new MyGenericClass<TSomeClass>();
myGenericInstance.MyGenericMethod<TSomeClass, TSomeInterface>();
It will be a compile error if the type parameter MyGenericClass is declared with does not match the first type parameter to MyGenericMethod.
Since the first type parameter can be inferred by the this argument, it is often possible for the compiler to infer both type parameters if their additional parameters to the method.
In C#, what is the preferred way to add (deep) copy functionality to a class? Should one implement the copy constructor, or rather derive from ICloneable and implement the Clone() method?
Remark: I wrote "deep" within brackets because I thought it was irrelevant. Apparently others disagree, so I asked whether a copy constructor/operator/function needs to make clear which copy variant it implements.
You should not derive from ICloneable.
The reason is that when Microsoft designed the .net framework they never specified whether the Clone() method on ICloneable should be a deep or shallow clone, thus the interface is semantically broken as your callers won't know whether the call will deep or shallow clone the object.
Instead, you should define your own IDeepCloneable (and IShallowCloneable) interfaces with DeepClone() (and ShallowClone()) methods.
You can define two interfaces, one with a generic parameter to support strongly typed cloning and one without to keep the weakly typed cloning ability for when you are working with collections of different types of cloneable objects:
public interface IDeepCloneable
{
object DeepClone();
}
public interface IDeepCloneable<T> : IDeepCloneable
{
T DeepClone();
}
Which you would then implement like this:
public class SampleClass : IDeepCloneable<SampleClass>
{
public SampleClass DeepClone()
{
// Deep clone your object
return ...;
}
object IDeepCloneable.DeepClone()
{
return this.DeepClone();
}
}
Generally I prefer to use the interfaces described as opposed to a copy constructor it keeps the intent very clear. A copy constructor would probably be assumed to be a deep clone, but it's certainly not as much of a clear intent as using an IDeepClonable interface.
This is discussed in the .net Framework Design Guidelines and on Brad Abrams' blog
(I suppose if you are writing an application (as opposed to a framework/library) so you can be sure no one outside of your team will be calling your code, it doesn't matter so much and you can assign a semantic meaning of "deepclone" to the .net ICloneable interface, but you should make sure this is well documented and well understood within your team. Personally I'd stick to the framework guidelines.)
In C#, what is the preferred way to add (deep) copy functionality to a class?
Should one implement the copy constructor,
or rather derive from ICloneable and implement the Clone() method?
The problem with ICloneable is, as others have mentioned, that it does not specify whether it is a deep or shallow copy, which makes it practically unuseable and, in practice, rarely used. It also returns object, which is a pain, since it requires a lot of casting. (And though you specifically mentioned classes in the question, implementing ICloneable on a struct requires boxing.)
A copy constuctor also suffers from one of the problems with ICloneable. It isn't obvious whether a copy constructor is doing a deep or shallow copy.
Account clonedAccount = new Account(currentAccount); // Deep or shallow?
It would be best to create a DeepClone() method. This way the intent is perfectly clear.
This raises the question of whether it should be a static or instance method.
Account clonedAccount = currentAccount.DeepClone(); // instance method
or
Account clonedAccount = Account.DeepClone(currentAccount); // static method
I slightly prefer the static version sometimes, just because cloning seems like something that is being done to an object rather than something the object is doing. In either case, there are going to be issues to deal with when cloning objects that are part of an inheritence hierarchy, and how those issues are delt with may ultimately drive the design.
class CheckingAccount : Account
{
CheckAuthorizationScheme checkAuthorizationScheme;
public override Account DeepClone()
{
CheckingAccount clone = new CheckingAccount();
DeepCloneFields(clone);
return clone;
}
protected override void DeepCloneFields(Account clone)
{
base.DeepCloneFields(clone);
((CheckingAccount)clone).checkAuthorizationScheme = this.checkAuthorizationScheme.DeepClone();
}
}
I recommend using a copy constructor over a clone method primarily because a clone method will prevent you from making fields readonly that could have been if you had used a constructor instead.
If you require polymorphic cloning, you can then add an abstract or virtual Clone() method to your base class that you implement with a call to the copy constructor.
If you require more than one kind of copy (ex: deep/shallow) you can specify it with a parameter in the copy constructor, although in my experience I find that usually a mixture of deep and shallow copying is what I need.
Ex:
public class BaseType {
readonly int mBaseField;
public BaseType(BaseType pSource) =>
mBaseField = pSource.mBaseField;
public virtual BaseType Clone() =>
new BaseType(this);
}
public class SubType : BaseType {
readonly int mSubField;
public SubType(SubType pSource)
: base(pSource) =>
mSubField = pSource.mSubField;
public override BaseType Clone() =>
new SubType(this);
}
There is a great argument that you should implement clone() using a protected copy constructor
It is better to provide a protected (non-public) copy constructor and invoke that from the clone method. This gives us the ability to delegate the task of creating an object to an instance of a class itself, thus providing extensibility and also, safely creating the objects using the protected copy constructor.
So this is not a "versus" question. You may need both copy constructor(s) and a clone interface to do it right.
(Although the recommended public interface is the Clone() interface rather than Constructor-based.)
Don't get caught-up in the explicit deep or shallow argument in the other answers. In the real world it is almost always something in-between - and either way, should not be the caller's concern.
The Clone() contract is simply "won't change when I change the first one". How much of the graph you have to copy, or how you avoid infinite recursion to make that happen shouldn't concern the caller.
Implementing ICloneable's not recommended due to the fact that it's not specified whether it's a deep or shallow copy, so I'd go for the constructor, or just implement something yourself. Maybe call it DeepCopy() to make it really obvious!
You'll run into problems with copy constructors and abstract classes. Imagine you want to do the following:
abstract class A
{
public A()
{
}
public A(A ToCopy)
{
X = ToCopy.X;
}
public int X;
}
class B : A
{
public B()
{
}
public B(B ToCopy) : base(ToCopy)
{
Y = ToCopy.Y;
}
public int Y;
}
class C : A
{
public C()
{
}
public C(C ToCopy)
: base(ToCopy)
{
Z = ToCopy.Z;
}
public int Z;
}
class Program
{
static void Main(string[] args)
{
List<A> list = new List<A>();
B b = new B();
b.X = 1;
b.Y = 2;
list.Add(b);
C c = new C();
c.X = 3;
c.Z = 4;
list.Add(c);
List<A> cloneList = new List<A>();
//Won't work
//foreach (A a in list)
// cloneList.Add(new A(a)); //Not this time batman!
//Works, but is nasty for anything less contrived than this example.
foreach (A a in list)
{
if(a is B)
cloneList.Add(new B((B)a));
if (a is C)
cloneList.Add(new C((C)a));
}
}
}
Right after doing the above, you start wishing you'd either used an interface, or settled for a DeepCopy()/ICloneable.Clone() implementation.
The problem with ICloneable is both intent and consistency. It's never clear whether it is a deep or shallow copy. Because of that, it's probably never used in only one manner or another.
I don't find a public copy constructor to be any clearer on that matter.
That said, I would introduce a method system that works for you and relays intent (a'la somewhat self documenting)
If the object you are trying to copy is Serializable you can clone it by serializing it and deserializing it. Then you don't need to write a copy constructor for each class.
I don't have access to the code right now but it is something like this
public object DeepCopy(object source)
{
// Copy with Binary Serialization if the object supports it
// If not try copying with XML Serialization
// If not try copying with Data contract Serailizer, etc
}
It is dependent on copy semantics of the class in question, which you should define yourself as the developer. Chosen method is usually based on intended use cases of the class. Maybe it will make a sense to implement both methods. But both share similar disadvantage - it is not exactly clear which copying method they implement. This should be clearly stated in documentation for your class.
For me having:
// myobj is some transparent proxy object
var state = new ObjectState(myobj.State);
// do something
myobject = GetInstance();
var newState = new ObjectState(myobject.State);
if (!newState.Equals(state))
throw new Exception();
instead of:
// myobj is some transparent proxy object
var state = myobj.State.Clone();
// do something
myobject = GetInstance();
var newState = myobject.State.Clone();
if (!newState.Equals(state))
throw new Exception();
looked as clearer statement of intent.
I think there should be a standard pattern for cloneable objects, though I'm not sure what exactly the pattern should be. With regard to cloning, it would seem there are three types of classes:
Those that explicitly support for deep cloning
Those that where memberwise cloning will work as deep cloning, but which neither have nor need explicit support.
Those which cannot be usefully deep cloned, and where memberwise cloning will yield bad results.
So far as I can tell, the only way (at least in .net 2.0) to get a new object of the same class as an existing object is to use MemberwiseClone. A nice pattern would seem to be to have a "new"/"Shadows" function Clone which always returns the present type, whose definition is always to call MemberwiseClone and then call a protected virtual subroutine CleanupClone(originalObject). The CleanupCode routine should call base.Cleanupcode to handle the base type's cloning needs and then add its own cleanup. If the cloning routine has to use the original object, it would have to be typecast, but otherwise the only typecasting would be on the MemberwiseClone call.
Unfortunately, the lowest level of class that was of type (1) above rather than type (2) would have to be coded to assume that its lower types would not need any explicit support for cloning. I don't really see any way around that.
Still, I think having a defined pattern would be better than nothing.
Incidentally, if one knows that one's base type supports iCloneable, but does not know the name of the function it uses, is there any way to reference the iCloneable.Clone function of one's base type?
If you read through all the interesting answers and discussions, you might still ask yourself how exactly you copy the properties - all of them explicitly, or is there a more elegant way to do it? If that is your remaining question, take a look at this (at StackOverflow):
How can I “deeply” clone the properties of 3rd party classes using a generic extension method?
It describes how to implement an extension method CreateCopy() which creates a "deep" copy of the object including all properties (without having to copy property by property manually).
I have a method
private object SetGrid(IGrid grid)
{
grid.PagerHelper.SetPage(1, 10);
grid.SortHelper.SetSort(SortOperator.Ascending);
grid.PagerHelper.RecordsPerPage = 10;
return grid;
}
which returns an object of type object.
Then I cast the object back to the previous type.
var projectModel = new ProjectModel();
projektyModel = (ProjectModel)SetGrid(projectModel);
The gain of this is, the method SetGrid can be reused across the app.
Is this a common practice or should I avoid doing this ?
You could use a generic method instead, and constrain the type argument to your IGrid interface:
private T SetGrid<T>(T grid) where T : IGrid
{
grid.PagerHelper.SetPage(1, 10);
grid.SortHelper.SetSort(SortOperator.Ascending);
grid.PagerHelper.RecordsPerPage = 10;
return grid;
}
You should still be able to call the method in exactly the same way, just without the cast. Type inferencing should be capable of automagically figuring out the required generic type argument for you:
var projectModel = new ProjectModel();
projektyModel = SetGrid(projectModel);
EDIT...
As other answers have mentioned, if your IGrid objects are reference types then you don't actually need to return anything at all from your method. If you pass a reference type then your method will update the original object, not a copy of it:
var projectModel = new ProjectModel(); // assume that ProjectModel is a ref type
projektyModel = SetGrid(projectModel);
bool sameObject = object.ReferenceEquals(projectModel, projektyModel); // true
Since you are passing in an object of a class that implements IGrid you could just as well change the return type to IGrid.
Also, since it's a reference type you don't even need to return the grid again. You could just as well use this:
var projectModel = new ProjectModel();
SetGrid(projectModel);
This is better accomplished with generics. You can use a constraint on the generic typeparam to preserve your type safety!
private T SetGrid<T>(T grid) where T : IGrid
{
grid.PagerHelper.SetPage(1, 10);
grid.SortHelper.SetSort(SortOperator.Ascending);
grid.PagerHelper.RecordsPerPage = 10;
return grid;
}
and then
var projectModel = new ProjectModel();
projectModel = SetGrid(projectModel);
Here, the generic typeparam "T" is actually inferred by the compiler by the way you call the method.
It's worth noting that in the particular use-case you've demonstrated, returning grid is probably unnecessary, as your original variable reference will be appropriately modified after the method call.
In the case you illustrate above there is no need to return grid. The IGrid instance is passed by reference, so your projectModel reference will be updated with the changes you've made in the SetGrid method.
If you still want to return the argument, at least return IGrid, since it is already known that the argument is an IGrid.
In general, provide as much type information as you can when programming in a statically typed language/manner.
"Is this a common practice or should I avoid doing this ?"
This is not common practice. You should avoid doing this.
Functions that only modify the parameter passed in should not have return types. If causes a bit of confusion. In the current C# you could make the modifying function an extention method for better read-ability.
It causes an unnecisary cast of the return type. It's a performance decrease, which may not be noticable... but its still needless since you are casting from an interface, return that interface even if the object is different from the parameter passed in.
Returning object is confusing to users of the function. Lets say the function created a copy and returned a copy... you would still want to return the interface passed in so that people using the function know "hey i'm getting an IGrid back." instead of having to figure out what type is being returned on thier own. The less you make your team mates think about stuff like this the better, for you and them.
This is a very weird example because SetGrid doesn't seem to do a lot of things other than setting some defaults. You are also letting the code perform manipulation on the object that could very well do that by itself. Meaning IGrid and ProjectModel could be refactored to this:
public interface IGrid {
// ...
public void setDefaults();
// ...
}
public class ProjectModel : IGrid {
// ...
public void setDefaults() {
PagerHelper.SetPage(1, 10);
SortHelper.SetSort(SortOperator.Ascending);
PagerHelper.RecordsPerPage = 10;
}
// ...
}
Using this refactoring you only need perform the same with this:
myProjectModel.setDefaults();
You could also create an abstract base class that implements IGrid that implements the setDefaults() method and let ProjectModel extend the abstract class.
what about the SOLID principles ? Concretely the Single Responsibility Principle. The class is in the first place something like a DTO. – user137348
I'm exercising the Interface Segregation Principle out of the SOLID principles here, to hide the implementation from the client of the class. I.e. so the client doesn't have to access the internals of the class it is using or else it is a violation of Principle of Least Knowledge.
Single Responsibility Principle (SRP) only tells that a class should only have one reason to change which is a very vague restriction since a change can be as narrow and broad as you want it to be.
I believe it is okay to put some configuration logic in a parameter class if it is small enough. Otherwise I'd put it all in a factory class. The reason I suggest this solution is because IGrid seems to have reference to PagerHelper and SortHelper that seem to be mutators for IGrid.
So I find it odd that you mention the class being a DTO. A DTO from a purist sense shouldn't have logic in it other than accessors (i.e. getter methods) which makes it strange that ProjectModel itself has references to PagerHelper and SortHelper which I assume can mutate it (i.e. they're setters). If you really want SRP the "helpers" should be in a factory class that creates the IGrid/ProjectModel instance.
Your grid is an IGrid, why not return IGrid?