How to Override C# Virtual Methods Effectively