2009-03-02 3 views
11

В C# у меня есть базовый класс продукта и виджет производного класса.C#: Как вызвать статический метод базового класса из статического метода производного класса?

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

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

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

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

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

+1

Любая причина, почему данный метод является статическим? – Rad

ответ

16

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

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

using mybaseclass = Namespace.BaseClass; 

class MyClass : mybaseclass { 

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

} 
+4

> Статические методы в основном являются методом возврата ... Почему это правда? В коде для моего класса методы, которые полагаются на данные экземпляра, являются методами экземпляра. Методы, которые не зависят от данных экземпляра, но зависят только от параметров (если они есть), являются статическими методами. Я считаю это различие полезным. – MindModel

+0

Метод, который не полагается на экземпляр * object *, не воспроизводится большинством правил, определенных для объектов (диспетчеризация виртуальных методов, ...). –

+0

mindmodel, в то время как для него есть некоторые сценарии, если вы начинаете нуждаться в наследовании или [вставляете какое-либо другое ограничение против нестатических методов], это симптом, что что-то еще может быть отключено ... возможно, у класса слишком много обязанностей – eglasius

0

Имея в виду, что статический метод shoudn't ретранслировать в данных экземпляра ... вы должны иметь статический «MyMethod», который ведет себя Diferent на основе параметра или что-то подобное.

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

EDIT: Я думаю, ваш лучший выбор, чтобы использовать Product.MyMethod явно ... Если вы думаете ... это should't быть вероятно, что ваш виджет изменить свою базовую Clase ... а также в том, что это незначительное изменение кода.

+0

Не совсем верно. статические методы могут полагаться на частные члены типа (как статические, так и экземпляры), в результате они не полностью перемещаются. –

+0

Правда. Вы знаете разницу между статическими переменными (по одному на класс) и переменными экземпляра (по одному на один экземпляр). Почему это различие не полезно? Почему это плохой дизайн OO? – MindModel

+0

Ну, я должен был сказать, что вы «не должны» не передавать в переменных переменных экземпляра ... конечно, вы «МОЖЕТ». :) – Romias

1

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

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

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

  • Отражение
  • Aliasing базовый класс (например, Mehrdad's example)
4

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

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); 
    } 
} 
+4

Достаточно честный. В этом случае решение хуже проблемы. Благодарю. – MindModel

+0

Точно. Десять символов – marcumka

+2

Вместо использования строки вы можете использовать MethodBase.GetCurrentMethod(). Имя –

0

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

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

4

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

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

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

-1

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

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();    
    } 
} 
+0

Aaron, OP имеет то же имя метода для базового и производного классов. Наряду с тем, что она не хочет явно указывать «Base.StaticMethod» явно, эти две суть проблемы. – nawfal

2

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

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

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

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

2

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

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

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

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

Смежные вопросы