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

Компилятор С#: не может получить доступ к статическому методу в нестационарном контексте

У меня есть код ниже:

public class Anything
{
    public int Data { get; set;}
}

public class MyGenericBase<T>
{
    public void InstanceMethod(T data)
    {
        // do some job
    }

    public static void StaticMethod(T data)
    {
        // do some job
    }

    // others members...
}

public sealed class UsefulController : MyGenericBase<Anything>
{
    public void ProxyToStaticMethod()
    {
        StaticMethod(null);
    }

    // others non derived members...
}

public class Container
{
    public UsefulController B { get; set; }
}

public class Demo
{
    public static void Test()
    {
        var c = new Container();
        c.B.InstanceMethod(null);   // Works as expected.
        c.B.StaticMethod(null);     // Doesn't work. 
                                    // Static method call on object rather than type. 
                                    // How to get the static method on the base type ?
        c.B.ProxyToStaticMethod();  // Works as expected.
    }
}

Компилятор очень злится... Я понимаю сообщение об ошибке, но я не знаю, как это решить. Я пытался получить тип, а не объект для вызова моего статического метода, но я не нашел способ сделать это правильно. Более того, это приводит к чему-то не совсем элегантному.

В принципе, GenericBase - это класс из фреймворка с множеством статических методов и некоторых методов экземпляра. Контроллер печатает этот класс и расширяет его.

Контейнер представляет собой группу логически связанных контроллеров.

Интересная вещь: Java-версия этого кода компилируется правильно, но с предупреждением. Выполнение также является правильным.

Существует ли шаблон проектирования для решения этой проблемы?

Спасибо за ваши данные!


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

    public class GenericBase<T> : MyGenericBase<T>
{
    // Create instance calls here for every base static method.
}

public sealed class UsefulController : GenericBase<Anything>
{
    // others non derived members...
}
4b9b3361

Ответ 1

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

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

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

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

Ответ 2

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

 MyGenericBase<Anything>.StaticMethod( null );

Ответ 3

Вы не можете сделать это на С#. Вы можете сделать это на VB.NET и Java, но, честно говоря, это не имеет смысла. Это просто дает вам ложное чувство полиморфизма в методе static, который не является реальным никакими средствами. Поскольку он не является полиморфным, весь вызов метода известен во время компиляции (статически), и вы можете указать вызов непосредственно с именем класса.

Ответ 4

Вы можете сделать одно из следующих:

UsefulController.StaticMethod(null);  
MyGenericBase<Anything>.StaticMethod(null);  

Использование экземпляра невозможно, как уже объяснялось другими.