Por que não pode ter métodos estáticos abstratas em C #?

votos
158

Eu tenho trabalhado com provedores de um bocado ultimamente, e me deparei com uma situação interessante onde eu queria ter uma classe abstrata que tinha um método estático abstrato. Eu li alguns posts sobre o tema, e isso meio que fazia sentido, mas há uma boa explicação clara?

Publicado 06/08/2008 em 12:04
fonte usuário
Em outras línguas...                            


7 respostas

votos
146

Os métodos estáticos não são instanciado como tal, eles estão apenas disponíveis sem uma referência de objeto.

Uma chamada para um método estático é feito através do nome da classe, não através de uma referência de objeto, e o código IL para chamar ele irá chamar o método abstrato através do nome da classe que definiu, não necessariamente o nome da 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, como este:

class Program
{
    static void Main(string[] args)
    {
        B.Test();
    }
}

Em seguida, o código real dentro do método principal é a 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 era a Uma classe que definiu, e não para B.Test, mesmo que você pode escrever o código dessa maneira.

Se você tivesse tipos de classe , como em Delphi, onde você pode fazer uma variável referente a um tipo e não um objeto, você teria mais uso para métodos virtuais e, portanto, abstratos estáticos (e também de construtores), mas eles não estão disponíveis e assim chamadas estáticas são não-virtual em .NET.

Eu percebo que os designers IL poderia permitir que o código para ser compilado para chamar B.Test, e resolver a chamada em tempo de execução, mas ainda não seria virtual, como você ainda teria que escrever algum tipo de nome da classe lá.

métodos virtuais e os assim abstratas, só são úteis quando você estiver usando uma variável que, em tempo de execução, pode conter muitos tipos diferentes de objetos, e você assim quiser chamar o método correto para o objeto atual que você tem na variável. Com métodos estáticos que você precisa passar por um nome de classe de qualquer maneira, de modo que o método exato para chamar é conhecido em tempo de compilação, porque ele não pode e não vai mudar.

Assim, os métodos estáticos virtuais / abstratas não estão disponíveis em .NET.

Respondeu 06/08/2008 em 12:30
fonte usuário

votos
42

Os métodos estáticos não podem ser herdadas ou substituído, e é por isso que não pode ser abstrato. Desde métodos estáticos são definidos no tipo, não a caso, de uma classe, eles devem ser chamados explicitamente esse tipo. Então, quando você quiser chamar um método em uma classe filha, você precisa usar seu nome para chamá-lo. Isso faz com que a herança irrelevante.

Suponha que você poderia, por um momento, herdar métodos estáticos. Imagine este cenário:

public static class Base
{
    public static virtual int GetNumber() { return 5; }
}

public static class Child1 : Base
{
    public static override int GetNumber() { return 1; }
}

public static class Child2 : Base
{
    public static override int GetNumber() { return 2; }
}

Se você chamar Base.GetNumber (), que método seria chamado? Que valor retornado? Sua muito fácil ver que sem criar instâncias de objetos, a herança é bastante difícil. métodos abstratos sem herança são apenas métodos que não têm um corpo, por isso não pode ser chamado.

Respondeu 06/08/2008 em 12:21
fonte usuário

votos
15

Outro entrevistado (McDowell) disse que o polimorfismo só funciona para instâncias de objetos. Isso deve ser qualificado; há línguas que fazem aulas de tratar como instâncias de um tipo "Classe" ou "metaclasse". Estas línguas não apoiar polimorfismo tanto para classes métodos (estáticos) instância e.

C #, como Java e C ++, antes disso, não é um tipo de linguagem; a staticpalavra-chave seja explicitamente utilizado para designar que o método é estaticamente-ligado, em vez de dinâmico / virtual.

Respondeu 09/08/2008 em 08:01
fonte usuário

votos
8

Aqui é uma situação onde não é definitivamente uma necessidade de herança para os campos estáticos e métodos:

abstract class Animal
{
  protected static string[] legs;

  static Animal() {
    legs=new string[0];
  }

  public static void printLegs()
  {
    foreach (string leg in legs) {
      print(leg);
    }
  }
}


class Human: Animal
{
  static Human() {
    legs=new string[] {"left leg", "right leg"};
  }
}


class Dog: Animal
{
  static Dog() {
    legs=new string[] {"left foreleg", "right foreleg", "left hindleg", "right hindleg"};
  }
}


public static void main() {
  Dog.printLegs();
  Human.printLegs();
}


//what is the output?
//does each subclass get its own copy of the array "legs"?
Respondeu 18/02/2010 em 06:36
fonte usuário

votos
8

Para adicionar as explicações anteriores, chamadas de método estático são obrigados a um método específico em tempo de compilação , que em vez exclui o comportamento polimórfico.

Respondeu 06/08/2008 em 12:24
fonte usuário

votos
4

Nós realmente substituir métodos estáticos (em Delphi), que é um pouco feio, mas ele funciona muito bem para as nossas necessidades.

Vamos utilizá-lo de modo que as classes podem ter uma lista de seus objetos disponíveis sem a instância de classe, por exemplo, temos um método que se parece com isso:

class function AvailableObjects: string; override;
begin
  Result := 'Object1, Object2';
end; 

É feio, mas necessário, desta forma podemos instanciar apenas o que é necessário, em vez de ter todas as classes instantianted apenas para procurar os objetos disponíveis.

Este foi um exemplo simples, mas a aplicação em si é uma aplicação cliente-servidor que tem todas as classes disponíveis em apenas um servidor e vários clientes diferentes, que não pode precisar tudo o que o servidor tem e nunca terá uma instância de objeto.

Portanto, este é muito mais fácil de manter do que ter um aplicativo de servidor diferente para cada cliente.

Espero que o exemplo era clara.

Respondeu 18/08/2008 em 20:01
fonte usuário

votos
0

Os métodos abstratos são implicitamente virtual. Abstratos métodos requerem uma instância, mas os métodos estáticos não têm uma instância. Assim, você pode ter um método estático em uma classe abstrata, ele simplesmente não pode ser abstrato estática (ou estático abstrato).

Respondeu 14/05/2009 em 12:11
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more