Почему я не могу иметь абстрактные статические методы в C #?
90519 просмотра
7 ответа
В последнее время я довольно много работал с провайдерами и столкнулся с интересной ситуацией, когда мне захотелось иметь абстрактный класс с абстрактным статическим методом. Я прочитал несколько постов на эту тему, и это вроде как имело смысл, но есть ли хорошее четкое объяснение?
Автор: lomaxx Источник Размещён: 17.05.2019 02:33Ответы (7)
147 плюса
Статические методы не создаются как таковые, они просто доступны без ссылки на объект.
Вызов статического метода выполняется через имя класса, а не через ссылку на объект, а код Intermediate Language (IL) для его вызова вызовет абстрактный метод через имя класса, который его определил, а не обязательно имя класс, который вы использовали.
Позвольте мне показать пример.
Со следующим кодом:
public class A
{
public static void Test()
{
}
}
public class B : A
{
}
Если вы звоните B.Test, вот так:
class Program
{
static void Main(string[] args)
{
B.Test();
}
}
Тогда фактический код внутри метода Main выглядит следующим образом:
.entrypoint
.maxstack 8
L0000: nop
L0001: call void ConsoleApplication1.A::Test()
L0006: nop
L0007: ret
Как видите, вызов сделан в A.Test, потому что его определил класс A, а не B.Test, даже если вы можете написать код таким способом.
Если бы у вас были классовые типы , как в Delphi, где вы можете создать переменную, ссылающуюся на тип, а не на объект, вы бы больше использовали виртуальные и, следовательно, абстрактные статические методы (а также конструкторы), но они недоступны и таким образом, статические вызовы не являются виртуальными в .NET.
Я понимаю, что разработчики IL могут позволить скомпилировать код для вызова B.Test и разрешить вызов во время выполнения, но он все равно не будет виртуальным, так как вам все равно придется написать какое-то имя класса.
Виртуальные методы, и, следовательно, абстрактные, полезны только тогда, когда вы используете переменную, которая во время выполнения может содержать много разных типов объектов, и, таким образом, вы хотите вызвать правильный метод для текущего объекта, который вы имеете в переменной. Со статическими методами вам все равно нужно пройти через имя класса, поэтому точный метод для вызова известен во время компиляции, потому что он не может и не будет меняться.
Таким образом, виртуальные / абстрактные статические методы не доступны в .NET.
Автор: Lasse Vågsæther Karlsen Размещён: 06.08.2008 11:3042 плюса
Статические методы не могут быть унаследованы или переопределены, и поэтому они не могут быть абстрактными. Поскольку статические методы определены для типа, а не для экземпляра класса, они должны вызываться явно для этого типа. Поэтому, когда вы хотите вызвать метод в дочернем классе, вам нужно использовать его имя для его вызова. Это делает наследство неактуальным.
Предположим, вы могли бы на мгновение наследовать статические методы. Представьте себе этот сценарий:
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; }
}
Если вы вызываете Base.GetNumber (), какой метод будет вызван? Какое значение вернулось? Довольно легко увидеть, что без создания экземпляров объектов наследование довольно сложно. Абстрактные методы без наследования - это просто методы, которые не имеют тела, поэтому не могут быть вызваны.
Автор: David Wengier Размещён: 06.08.2008 11:2115 плюса
Другой респондент (Макдауэлл) сказал, что полиморфизм работает только для экземпляров объектов. Это должно быть квалифицировано; Есть языки, которые рассматривают классы как экземпляры типа «Класс» или «Метакласс». Эти языки поддерживают полиморфизм как для экземпляров, так и для классов (статических) методов.
C #, как и Java и C ++ до него, не является таким языком; static
ключевое слово используется для обозначения явно , что метод статический переплета , а не динамических / виртуального.
8 плюса
Чтобы добавить к предыдущим объяснениям, вызовы статических методов привязываются к определенному методу во время компиляции , что скорее исключает полиморфное поведение.
Автор: Rytmis Размещён: 06.08.2008 11:248 плюса
Вот ситуация, когда определенно требуется наследование для статических полей и методов:
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"?
Автор: user275801
Размещён: 18.02.2010 05:36
5 плюса
Мы на самом деле переопределяем статические методы (в delphi), это немного уродливо, но прекрасно работает для наших нужд.
Мы используем его, чтобы у классов был список доступных объектов без экземпляра класса, например, у нас есть метод, который выглядит следующим образом:
class function AvailableObjects: string; override;
begin
Result := 'Object1, Object2';
end;
Это некрасиво, но необходимо, так как мы можем создавать именно то, что нужно, вместо того, чтобы создавать экземпляры всех классов просто для поиска доступных объектов.
Это был простой пример, но само приложение является клиент-серверным приложением, в котором все классы доступны только на одном сервере и несколько разных клиентов, которым может не понадобиться все, что есть на сервере, и никогда не понадобится экземпляр объекта.
Так что это гораздо проще поддерживать, чем иметь одно отдельное серверное приложение для каждого клиента.
Надеюсь, пример был ясен.
Автор: Fabio Gomes Размещён: 18.08.2008 07:010 плюса
Абстрактные методы неявно виртуальны. Абстрактные методы требуют экземпляра, но статические методы не имеют экземпляра. Таким образом, вы можете иметь статический метод в абстрактном классе, он просто не может быть статическим абстрактным (или абстрактным статическим).
Автор: AMing Размещён: 14.05.2009 11:11Вопросы из категории :
- c# Преобразовать десятичную в двойную?
- c# Как рассчитать чей-то возраст в C #?
- c# Как вы сортируете словарь по значению?
- c# В чем разница между int и Integer в Java и C #?
- c# Как создать новый экземпляр объекта из Типа
- c# Datatable против Dataset
- .net Действительно ли опечатанные классы действительно предлагают преимущества?
- .net Setting Objects to Null/Nothing after use in .NET
- .net Почему я не могу иметь абстрактные статические методы в C #?
- language-design Почему переменные не объявлены в «try» в области «catch» или «finally»?
- language-design Почему оператор switch был предназначен для перерыва?
- language-design Почему имена переменных не могут начинаться с цифр?
- language-design Почему Java не поддерживает целые числа без знака?
- language-design Почему C # и Java беспокоятся о «новом» операторе?