4

The most clear case of the problem is function Clone (just an EXAMPLE guys). Let's say you have BaseClass and DerivedClass -- unless I miss something, in both functions (Clone per each of the class) you create BaseClass and DerivedClass respectively but you return object actually. This is the problem if you want to work with "real" class.

So far I see only two workarounds to this problem:

1. each time cast the result of the function to appropriate class

var real_stuff = (RealStuff)x.Clone(); // I want real stuff

2. provide second function, so you would have Clone (if you work at base class level) and CloneThis (which result would change from class to class, if you want to work at given class level)

   public override object Clone()
    {
       return CloneThis();
    }
    public RealStuff CloneThis()
    {
       return new RealStuff(this);
    }

The first one is ugly, the second one is tiresome.

QUESTION: how do you deal with this issue?

Another thing -- please comment on this as well if you like -- is why when overriding the function signature checking is so strict? Besides "because it was designed that way" or Eric Lippert's favourite "because every feature requires..." ;-) I see no technical (and logical, and so on) problems with allowing to override a function with changed result type IF the overriden function result is derived from original function result type.

Example:

  class ClassA
  {
    public virtual ClassA GetIt() ...
  }

  class ClassB : ClassA
  {
    public override ClassB GetIt() ...
  }

Currently it is not correct code, but I think it technically could be, because ClassB is derived from ClassA. And whatever you do with the output, the "receiver" expects ClassA, so ClassB fullfils this requirement.

So you could write:

  ClassA class_a_b = new ClassB();
  ClassB class_b_b = new ClassB();

  ClassA result1 = class_b_b.GetIt();
  ClassA result2 = class_a_b.GetIt();
  ClassB result3 = class_b_b.GetIt();
  // incorrect, derived GetIt would be called OK, 
  // but the signature is taken from ClassA
  ClassB result4 = class_a_b.GetIt(); 

I also don't think with such capabilities anyone would be surprised by the behaviour, IMHO it is consistent.

Please keep your answers on-topic, "You shouldn't use ICloneable" is NOT on topic. Thank you.

greenoldman
  • 16,895
  • 26
  • 119
  • 185
  • Have you considered a public virtual T Clone method that can be overridden and is called without the type that is inferred Clone(myObj) ? – Mart May 26 '11 at 07:13
  • 1
    Possible duplication of http://stackoverflow.com/questions/536349/why-no-icloneablet and http://stackoverflow.com/questions/1048884/c-overriding-return-types – Paolo Tedesco May 26 '11 at 07:16
  • @Paolo Tedesco, the second one is good, thank you. This question is **DUPLICATE**, how can I close it? – greenoldman May 26 '11 at 07:29
  • @macias: I replied anyway, even if thought this is somehow a duplication, as I wanted to add something (about casting to base interface and implicit cast operators). However, I don't think you can close your own questions (people have to vote for them to be closed). – Paolo Tedesco May 26 '11 at 08:05
  • I believe you can delete your own questions, certainly I've followed some links to find "the author voluntarily removed this question" or something along those lines. – Smudge202 May 26 '11 at 08:37
  • The feature you want is called "return type covariance" and C# does not support it, sorry. (C++ does, incidentally.) Lots of people would like it, but it is unlikely to ever get implemented in C#. See http://stackoverflow.com/questions/5709034/does-c-support-return-type-covariance/5709191#5709191 for some thoughts. – Eric Lippert May 26 '11 at 15:14

1 Answers1

3

Check these two questions:

Basically, the way to deal with this is defining a generic interface with the appropriate return type, e.g.

interface ICloneable<T> {
    T Clone();
}

This, however, does not let you use the interface as a base type, because ICloneable<ClassOne> and ICloneable<ClassTwo> are two different things.

It would be "technically possible" to have functions differing only by return type, and infact the CLR allows this, but C# does not, possibly because it would be impossible to guess always the correct overload to call. (Actually with C# you can do this with implicit cast operators: they are compiled to functions with name op_Implicit and different return type).

Community
  • 1
  • 1
Paolo Tedesco
  • 55,237
  • 33
  • 144
  • 193
  • The second link is awesome, I already read it, not only the accepted answer is good, but other answers as well. I noticed at least 4 solid (!) approaches. Of course it would be better to have such capability out of the box. Just comment to your statement "it would be impossible to guess always the correct overload to call." It is NOT overloading, it is overriding (I asked about overriding), and it is always known which function to call, the one from compile time class level. – greenoldman May 26 '11 at 07:37