Javaに慣れた自分からすると見慣れないvirtualの使い方を整理してみようと思います。
基本的には親クラスにメソッドを宣言する際に、子クラスに対してこのメソッドはoverride可能だよと教えてくれるキーワードのようです。
たとえば、以下のような使い方。
class OyaClass
{
protected virtual void Test1()
{
Console.WriteLine("OyaClass:test1");
}
}
class KoClass: OyaClass
{
protected override void Test1()
{
Console.WriteLine("OyaClass:test1");
}
}
親クラスのメソッドがvirtualキーワードを使用して宣言されている為、子クラス側は心置きなくoverrideできます。
もし、virtual句が使用されていなかったら、以下のようなエラーが発生します。

一方、親クラスでvirtualを指定しておきながら、子クラス側で同じシグニチャのメソッドを宣言する際にoverrideキーワードを指定しないとどうなるか。
エラーにはなりませんが、警告がでます。

overrideしないならnew句をつけなさい、するならoverride句をつけなさい、って言われます。
で、newってなんだ?となります。
new句は、子クラス側から親クラスのメソッドをoverrideしないよと宣言するものです。
この場合、親クラスから子クラスのTest1メソッドを参照する事ができません。
class OyaClass
{
protected virtual void Test1()
{
Console.WriteLine("OyaClass:test1");
}
}
class KoClass: OyaClass
{
// 親クラスからは見えないメソッド
protected new void Test1()
{
Console.WriteLine("OyaClass:test1");
}
}
この状態で、クライアントクラスから以下のようにしてTest1メソッドを呼び出すと、
親クラスのTest1メソッドが呼び出されます。
OyaClass hoge = new KoClass();
hoge.Test1(); // OyaClassのTest1()が呼び出される。
つまり、子クラス側ではnewキーワードをつけることで、親クラスには参照させないよ、
という宣言をしてます。
もちろん、virtualキーワードをつけて子クラスのメソッドを宣言すれば子クラスのTest1()が呼び出されることになります。