C# virtual vs. abstract methods