Подтвердить что ты не робот

Можно ли переопределить статический метод в С#?

Мне сказали, что методы static неявно final и поэтому не могут быть переопределены. Это правда?

  • Может ли кто-нибудь дать лучший пример переопределения статического метода?

  • Если статические методы - это просто методы класса, каково их использование?

4b9b3361

Ответ 1

(1) Статические методы нельзя переопределить, однако они могут быть скрыты с использованием ключевого слова "новое". В основном методы переопределения означают, что вы ссылаетесь на базовый тип и хотите вызвать производный метод. Поскольку static являются частью типа и не подпадают под запросы vtable, которые не имеют смысла.

например. статика не может делать:

public class Foo { 
    public virtual void Bar() { ... }
}
public class Bar : Foo {
    public override void Bar() { ... }
}

// use:
Foo foo = new Bar(); // make an instance
foo.Bar(); // calls Bar::Bar

Поскольку статика не работает с экземплярами, вы всегда указываете Foo.Bar или Bar.Bar явно. Поэтому переопределение здесь не имеет смысла (попробуйте выразить его в коде...).

(2) Существуют разные способы использования статических методов. Например, он используется в шаблоне Singleton для получения одного экземпляра типа. Другим примером является "static void Main", который является основной точкой доступа в вашей программе.

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

[обновление]

Пример простого скрытия:

public class StaticTest
{
    public static void Foo() { Console.WriteLine("Foo 1"); }
    public static void Bar() { Console.WriteLine("Bar 1"); }
}

public class StaticTest2 : StaticTest
{
    public new static void Foo() { Console.WriteLine("Foo 2"); }
    public static void Some() { Foo(); Bar(); } // Will print Foo 2, Bar 1
}

public class TestStatic
{
    static void Main(string[] args)
    {
        StaticTest2.Foo();
        StaticTest2.Some();
        StaticTest.Foo();
        Console.ReadLine();
    }
}

Обратите внимание, что если вы создадите классы static, вы не сможете этого сделать. Статические классы должны быть получены из object.

Основное различие между этим и наследованием заключается в том, что компилятор может определить во время компиляции, какой метод вызывать при использовании static. Если у вас есть экземпляры объектов, вам нужно сделать это во время выполнения (это называется просмотром vtable).

Ответ 2

Вы не переопределяете статический метод. Вы прячете это. См. этот ответ для получения дополнительной информации.

Некоторые причины использования статических методов:

  • Они немного быстрее, чем методы экземпляра. Также см. Эту статью msdn article, в которой приведены номера производительности для резервного копирования этого значения (встроенный статический вызов avg 0.2 ns, статический вызов avg 6.1ns, встроенный вызов экземпляра avg 1.1 ns, вызов экземпляра avg 6.8 ns)
  • Меньше подробностей для записи - не нужно создавать экземпляр класса для доступа к ним (и создание экземпляров также может повлиять на производительность)

Ответ 3

Ну, вы не можете переопределить статический метод. Статический метод не может быть виртуальным, поскольку он не связан с экземпляром класса.

"Переопределенный" метод в производном классе на самом деле является новым методом, не связанным с тем, который определен в базовом классе (отсюда и новое ключевое слово).

Это важно понять: когда типы наследуются от других типов, они выполняют общий контракт, тогда как статические типы не связаны никаким контрактом (с точки зрения чистого ООП). В языке нет технического способа связать два статических типа вместе с договором о "наследовании". Если вы "переопределите" метод Log в двух разных местах.

Если вы думаете о переопределении статических методов, это не имеет смысла; для виртуальной отправки вам необходим фактический экземпляр объекта для проверки.

Статический метод также не может реализовать интерфейс; если этот класс реализует интерфейс IRolesService, то я бы сказал, что метод не должен быть статическим вообще. Лучше спроектировать, чтобы иметь метод экземпляра, так что вы можете заменить ваш MockRoleService реальным сервисом, когда будете готовы