С#: Как вызвать статический метод базового класса из статического метода производного класса?

В С# у меня есть базовый класс Product и производный класс Widget.

Продукт содержит статический метод MyMethod().

Я хочу вызвать статический метод Product.MyMethod() из статического метода Widget.MyMethod().

Я не могу использовать ключевое слово base, потому что это работает только с методами экземпляра.

Я могу явно вызвать Product.MyMethod(), но если позже я изменю Widget для вывода из другого класса, мне придется пересмотреть метод.

Есть ли какой-нибудь синтаксис в С#, подобный базе, который позволяет мне вызвать статический метод из базового класса из статического метода производного класса?

Ответ 1

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

Ближайшая вещь, о которой я могу думать, - это директива using.

using mybaseclass = Namespace.BaseClass;

class MyClass : mybaseclass {

  static void MyMethod() {  mybaseclass.BaseStaticMethod();  }

}

Ответ 2

Это можно сделать, но я не рекомендую его.

public class Parent1
{
    public static void Foo()
    {
        Console.WriteLine("Parent1");
    }
}

public class Child : Parent1
{
    public new static void Foo()
    {
        Type parent = typeof(Child).BaseType;
        MethodInfo[] methods = parent.GetMethods();
        MethodInfo foo = methods.First(m => m.Name == "Foo");
        foo.Invoke(null, null);
    }
}

Ответ 3

Вызов статического метода с использованием отражения точно такой же, как вызов метода экземпляра, за исключением того, что вы передаете значение null для экземпляра. Вам нужна FlattenHierarchy, потому что она определена у предка.

var type = assy.GetType("MyNamespace.MyType");
MethodInfo mi = type.GetMethod("MyStaticMethod", 
  BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy);
mi.Invoke(null, null);

Дальнейшее чтение и размышление оставляют меня задавать те же вопросы, что и другие, которые ответили: зачем использовать статические методы, подобные этому? Вы пытаетесь выполнить функциональное программирование, и если да, почему бы не использовать лямбда-выражения вместо этого? Если вам нужны полиморфные поведения с общим состоянием, методы экземпляров будут лучше.

Ответ 4

Прежде всего, если вы беспокоитесь о возвращении родительского класса, то вы, вероятно, неправильно наследуете. Наследование должно использоваться для установления отношений "is-a", а не просто для повторного использования кода. Если вам нужно только повторное использование кода, подумайте об использовании делегирования, а не о наследовании. Я предполагаю, что вы можете ввести промежуточный тип между подтипом и его родителем, но я бы позволил этой возможности управлять моим дизайном.

Во-вторых, если вам нужно использовать функциональность из базового класса, но расширьте его. И в случае использования сценария использования для статического метода, вы можете захотеть использовать какой-либо внешний класс для хранения функциональности. Классический случай для этого в моем сознании - это шаблон Factory. Один из способов реализации шаблона Factory - через Factory Методы, статический метод для класса, который создает экземпляр этого класса. Обычно конструктор защищен так, что метод Factory является единственным способом создания класса извне.

Один из способов подхода к повторному использованию с помощью методов Factory в иерархии наследования заключается в том, чтобы поместить общий код в защищенный метод и вызвать этот метод из метода Factory вместо прямого вызова базового класса Factory Метод из подтипов Factory Метод. Лучшая реализация может использовать один и тот же метод, но переместить методы Factory в класс Factory и использовать конструкторную логику (внутреннюю, а не частную), возможно, в сочетании с методом инициализации для создания объекта. Если поведение, которое вы наследуете, является внешним из класса (дешифрование/проверка/etc), вы можете использовать общие методы (или состав) в Factory, чтобы разрешить повторное использование между методами Factory.

Не зная цели использования статических методов, вам сложно дать точное направление, но, надеюсь, это поможет.

Ответ 5

Это можно сделать:

public class Parent1
{
    protected static void Foo()
    {
        Console.WriteLine("Parent1");
    }
}

public class Child : Parent1
{
    public static void Foo()
    {
        return Parent1.Foo();
    }
}

Может быть полезен для модульного тестирования защищенных статических методов (например).

Ответ 6

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

Попытка найти способ лечения статических методов как полиморфных возможна, но опасна, потому что сам язык ее не поддерживает.

Некоторые предложения:

  • Отражение
  • Слияние базового класса (например, Пример Mehrdad)

Ответ 7

Учитывая, что статический метод shudn't не ретранслирует данные экземпляра... у вас должен быть статический "MyMethod", который ведет себя по-другому на основе параметра или чего-то подобного.

Помните, что статический метод, определенный в одном классе, - это всего лишь способ заказать ваш код... но это то же самое, если этот метод помещен в другое место... потому что он не ретранслирует объект, на котором он размещен.

РЕДАКТИРОВАТЬ: Я думаю, что ваш лучший выбор - явно использовать Product.MyMethod... Если вы думаете, что это... не должно быть вероятным, что ваш виджет изменит базовый клас... а также в этом случае это незначительное изменение в коде.

Ответ 8

Статические методы - это методы класса. Они предназначены для методов, применимых ко всем экземплярам определенного класса. Таким образом, наследование этого метода не имеет смысла, поскольку оно изменит значение, применимое к экземплярам класса. Например, если вы зацикливали коллекцию продуктов (некоторые из виджета, некоторые нет) и называли MyMethod на каждом продукте, тогда метод, который был вызван, будет определяться экземпляром класса. Это нарушает цель статических методов.

Возможно, вы можете сделать что-то вроде более чистого, просто не используя статические методы вообще, потому что в вашем примере не похоже, что MyMethod применяется ко всем экземплярам Product. Однако вы можете добиться того же влияния, которое вы описываете, используя класс интерфейса, например "IMyMethod. Этот подход по-прежнему не использует статический метод. Думаю, я не вижу необходимости в статическом методе. Почему вы хотите использовать статический метод для начала?

Ответ 9

Это очень просто. Гораздо проще, чем использовать сглаживание, отражения и т.д. Возможно, это стало проще в новых добавлениях .NET, IDK, но это работает отлично. Точно так же, как с помощью методов экземпляра, доступ к базовым методам не требует использования base, он является необязательным, как правило, необходимым, если унаследовательный и базовый классы имеют метод с тем же именем. Даже без ключевого слова base вы можете получить доступ к статическим методам базового класса, как если бы они были в классе, из которого вы звоните. Я тестировал это только при вызове базового метода static из производного класса static. Не работает, если вы вызываете метод экземпляр для статического метода.

public class BaseThings
{
    protected static void AssertPermissions()
    {
        //something
    }
}

public class Person:BaseThings
{
    public static void ValidatePerson(Person person)
    {
        //just call the base static method as if it were in this class.
        AssertPermissions();            
    }
}