Почему у меня не может быть абстрактных статических методов в C#?

NullPointerException s - исключения, возникающие при попытке использовать ссылку, которая указывает на отсутствие местоположения в памяти (null), как если бы она ссылалась на объект. Вызов метода по нулевой ссылке или попытка получить доступ к полю нулевой ссылки вызовет функцию NullPointerException. Они наиболее распространены, но другие способы перечислены на странице NullPointerException javadoc.

Вероятно, самый быстрый пример кода, который я мог бы придумать для иллюстрации NullPointerException, be:

public class Example {

    public static void main(String[] args) {
        Object obj = null;
        obj.hashCode();
    }

}

В первой строке внутри main я явно устанавливаю ссылку Object obj равной null. Это означает, что у меня есть ссылка, но она не указывает на какой-либо объект. После этого я пытаюсь обработать ссылку так, как если бы она указывала на объект, вызывая метод на нем. Это приводит к NullPointerException, потому что нет кода для выполнения в местоположении, на которое указывает ссылка.

(Это техничность, но я думаю, что она упоминает: ссылка, которая указывает на null, равна 't то же, что и указатель C, указывающий на недопустимую ячейку памяти. Нулевой указатель буквально не указывает на в любом месте , который отличается от указаний на местоположение, которое оказывается недопустимым.)

173
задан Peter Mortensen 8 January 2011 в 22:20
поделиться

7 ответов

Статические методы не , инстанцировал как таковой, они просто доступны без ссылки на объект.

вызов А к статическому методу сделан через имя класса, не через ссылку на объект и код Промежуточного языка (IL) для вызова, это назовет абстрактный метод через название класса, который определил его, не обязательно название класса, который Вы использовали.

Позволяют мне показать пример.

Со следующим кодом:

public class A
{
    public static void Test()
    {
    }
}

public class B : A
{
}

, Если Вы называете B.Test, как это:

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

Тогда фактический код в Основном методе следующие:

.entrypoint
.maxstack 8
L0000: nop 
L0001: call void ConsoleApplication1.A::Test()
L0006: nop 
L0007: ret 

, Как Вы видите, вызов выполняется к A.Test, потому что это был класс, который определил его, а не к B.Test, даже при том, что можно записать коду тот путь.

, Если Вы имели типы классов , как в Дельфи, где можно сделать переменную, относящуюся к типу и не объекту, у Вас было бы больше использования для виртуального и таким образом абстрактных статических методов (и также конструкторы), но они не доступны, и таким образом статические вызовы являются невиртуальными в.NET.

я понимаю, что разработчики IL могли позволить коду быть скомпилированным, чтобы назвать B.Test и разрешить вызов во времени выполнения, но это все еще не было бы виртуальным, поскольку необходимо будет все еще записать некоторое имя класса там.

Виртуальные методы, и таким образом абстрактные, только полезны при использовании переменной, которая, во времени выполнения, может содержать много различных типов объектов, и Вы таким образом хотите назвать правильный метод для текущего объекта, который Вы имеете в переменной. Со статическими методами необходимо пройти имя класса так или иначе, таким образом, точный метод для вызова известен во время компиляции, потому что он не может и не изменяться.

Таким образом, виртуальные/абстрактные статические методы не доступны в.NET.

153
ответ дан konstantin 23 November 2019 в 20:37
поделиться

Статические методы не могут быть наследованы или переопределены, и именно поэтому они не могут быть абстрактными. Так как статические методы определяются на типе, не экземпляре, класса, их нужно назвать явно на том типе. Таким образом, когда Вы хотите назвать метод на дочернем классе, необходимо использовать его имя для вызова его. Это делает наследование не важным.

Предполагают, что Вы могли, на мгновение, наследовать статические методы. Вообразите этот сценарий:

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; }
}

, Если Вы называете Основу. GetNumber (), какой метод назвали бы? То, которые оценивают, возвратилось? Его довольно легкое, чтобы видеть, что, не создавая объекты-экземпляры, наследование довольно трудно. Абстрактные методы без наследования являются просто методами, которые не имеют тела, так не может быть назван.

43
ответ дан David Wengier 23 November 2019 в 20:37
поделиться

Другой респондент (McDowell) сказал, что полиморфизм только работает на экземпляры объектов. Это должно быть квалифицировано; существуют языки, которые действительно рассматривают классы как экземпляры типа "Класса" или "Метакласса". Эти языки действительно поддерживают полиморфизм и для экземпляра и для класса (статические) методы.

C#, как Java и C++ перед ним, не является таким языком; static ключевое слово используется явно, чтобы обозначить, что метод является статически ограниченным, а не динамическим/виртуальным.

17
ответ дан Chris Hanson 23 November 2019 в 20:37
поделиться

Для добавления к предыдущим объяснениям вызовы статического метода связываются с определенным методом в время компиляции , который скорее исключает полиморфное поведение.

8
ответ дан Rytmis 23 November 2019 в 20:37
поделиться

Мы на самом деле переопределяем статические методы (в Дельфи), это немного ужасно, но это работает просто великолепно для наших потребностей.

Мы используем его так, классы могут иметь список своих доступных объектов без экземпляра класса, например, у нас есть метод, который похож на это:

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

Это ужасно, но необходимо, этот способ, которым мы можем инстанцировать, что необходимо, вместо того, чтобы иметь все классы instantianted только для поиска доступных объектов.

Это было простым примером, но само приложение является клиент-серверным приложением, которое имеет все классы в наличии во всего одном сервере и нескольких различных клиентах, которым, возможно, не понадобилось бы все, сервер имеет и никогда не будет нуждаться в экземпляре объекта.

, Таким образом, это намного легче поддержать, чем наличие одного различного серверного приложения для каждого клиента.

Hope пример был ясен.

5
ответ дан Fabio Gomes 23 November 2019 в 20:37
поделиться

Абстрактные методы неявно виртуальны. Абстрактные методы требуют экземпляра, но статические методы не имеют экземпляра. Итак, у вас может быть статический метод в абстрактном классе, он просто не может быть статическим абстрактным (или абстрактным статическим).

0
ответ дан 23 November 2019 в 20:37
поделиться

Вот ситуация, когда определенно существует необходимость в наследовании для статических полей и методов:

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"?
8
ответ дан 23 November 2019 в 20:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: