Os métodos estáticos não são instanciados como tal, apenas estão disponíveis sem uma referência a objeto.
Uma chamada para um método estático é feita através do nome da classe, não através de uma referência a objeto, e o código da Linguagem Intermediária (IL) para chamá-lo chamará o método abstrato pelo nome da classe que a definiu, não necessariamente pelo nome de a classe que você usou.
Deixe-me mostrar um exemplo.
Com o seguinte código:
public class A
{
public static void Test()
{
}
}
public class B : A
{
}
Se você chamar B.Test, assim:
class Program
{
static void Main(string[] args)
{
B.Test();
}
}
Em seguida, o código real dentro do método Main é o seguinte:
.entrypoint
.maxstack 8
L0000: nop
L0001: call void ConsoleApplication1.A::Test()
L0006: nop
L0007: ret
Como você pode ver, a chamada é feita para A.Test, porque foi a classe A que a definiu, e não para B.Test, mesmo que você possa escrever o código dessa maneira.
Se você tivesse tipos de classe , como no Delphi, onde você pode criar uma variável referente a um tipo e não a um objeto, teria mais utilidade para métodos estáticos virtuais e, portanto, abstratos (e também construtores), mas eles não estão disponíveis e portanto, as chamadas estáticas não são virtuais no .NET.
Percebo que os designers de IL podem permitir que o código seja compilado para chamar B.Test e resolver a chamada em tempo de execução, mas ainda assim não seria virtual, pois você ainda teria que escrever algum tipo de nome de classe lá.
Métodos virtuais e, portanto, abstratos, são úteis apenas quando você está usando uma variável que, em tempo de execução, pode conter muitos tipos diferentes de objetos e, portanto, você deseja chamar o método correto para o objeto atual que você possui na variável. Com os métodos estáticos, você precisa passar pelo nome de uma classe de qualquer maneira; portanto, o método exato a ser chamado é conhecido no momento da compilação, porque não pode e não muda.
Portanto, métodos estáticos virtuais / abstratos não estão disponíveis no .NET.