3

I've been reading the book CLR via C# by Jeffrey Richter and he argues that when defining a method in a base class, If there is a method you want to declare as virtual and it has a few convenience overloads, the most complex method should be the virtual method and the others should be left as non-virtual. Here is the example he gives:

public class Set {
    private Int32 m_length = 0;
    // This convenience overload is not virtual
    public Int32 Find(Object value) {
        return Find(value, 0, m_length);
    }
    // This convenience overload is not virtual
    public Int32 Find(Object value, Int32 startIndex) {
        return Find(value, startIndex, m_length - startIndex);
    }
    // The most feature-rich method is virtual and can be overridden
    public virtual Int32 Find(Object value, Int32 startIndex, Int32 endIndex) {
        // Actual implementation that can be overridden goes here...
    }
    // Other methods go here
}

What is the rational here?

Farhad Alizadeh Noori
  • 2,276
  • 17
  • 22
  • It seems to me that he is just giving an example of [polymorphism](http://msdn.microsoft.com/en-us/library/ms173152.aspx) with his overloading. As to why you would use `virtual` [this](http://stackoverflow.com/questions/1062102/practical-usage-of-virtual-functions-in-c-sharp) is a pretty good answer. – Brian Oct 09 '14 at 15:06
  • No, actually the book is about CLR. Polymorphism is kind of regarded as a known concept in this book. This is actually an example on why when having many different convenience overloads, you should always only set the more complex one as virtual and leave the rest and non-virtual. – Farhad Alizadeh Noori Oct 09 '14 at 15:11
  • He says doing so makes it more polymorphic? Is that because there is only one method overridable and not many? And if so, why is that more polymorphic? – Farhad Alizadeh Noori Oct 09 '14 at 15:12
  • I'd never heard this before, but it makes sense. I'd love to see someone come up with an example with inheriting class where it works well. – David Crowell Oct 09 '14 at 15:27
  • 1
    Well, there's nothing technically wrong with making all the overloads virtual, but I think the idea is that just the primary method, the one that takes all the parameters, is the only one that *needs* to be overridden. The others merely proxy to this main method forwarding their parameters and passing null or some default value for the rest. Those will continue to work just as well no matter how many times the primary method is overridden in whatever inheritance structure exists. – Chris Pratt Oct 09 '14 at 18:54

4 Answers4

3

The answer is - DRY principle - a single source of truth. There is method A which is most complex. B, C and D all use subsets of its functionality. So the programmer created this way, and all further code modifications are based on the assumption you keep relation between A, B, C, D. If you allow all of B, C, D be overridable, you are breaking the idea that was put in the class.

Code readability suffers, people read your base class, compose a picture of how it can work, then read your class, and figure that what they just learned is not the case with YOUR implementation. Makes team work hard. Also when you are reading your code 5 years later (if it needs to happen).

Victor Zakharov
  • 25,801
  • 18
  • 85
  • 151
2

The reason is that all the simpler methods are implemented by calling the virtual method. If these were made virtual you could potentially break this contract. By only allowing you to change the implementation specializations of this class will follow the same contract for these methods.

Brian Rasmussen
  • 114,645
  • 34
  • 221
  • 317
0

I would agree with Jeffrey; it makes sense to make virtual the most complex member as calls to the 'lesser' complex members will invoke the most complex one as they are called via method chaining. Further, it stands that the most complex member would likely be the one that contains all the parameters required to execute the function without any external dependencies.

I'll expand on this later on, if I can.

Dan
  • 10,282
  • 2
  • 37
  • 64
0

There is only one implementation, other overloads are simply forwarding a call. Making that one virtual make sense, as forwarding will still be working when implementation is overriden.

Sinatr
  • 20,892
  • 15
  • 90
  • 319