Почему может a.NET делегат не будет объявлен статическим?

когда я пытаюсь скомпилировать следующий:

public static delegate void MoveDelegate (Actor sender, MoveDirection args);

Я получаю, как ошибку: "modifer 'static' недопустим для этого элемента."

я реализую это внутри синглтона, с отдельным классом, который вызывает делегат. Проблема в том, что когда я использую экземпляр singleton в другом классе для вызова делегата (из идентификатора, а не типа), я не могу этого сделать по какой-либо причине, даже когда я объявляю делегат нестатическим. Очевидно, я могу только обратитесь к нему через тип напрямую, если и только если делегат статичен.

каковы причины этого? Я использую MonoDevelop 2.4.2.

обновление

после попытки одного из предложений со следующим кодом:

public void Move(MoveDirection moveDir)
{
    ProcessMove(moveDir);
}

public void ProcessMove(MoveDirection moveDir)
{
    Teleporter.MoveMethod mm = new Teleporter.MoveMethod(Move); 
    moveDelegate(this, moveDir);
}

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

6 ответов


попробуйте это:

public delegate void MoveDelegate(object o);
public static MoveDelegate MoveMethod;

таким образом, переменная метода может быть определена статической. Ключевое слово static не имеет значения для delegate определения , как enum или const определений.

пример того, как назначить статический метод-поле:

public class A
{
  public delegate void MoveDelegate(object o);
  public static MoveDelegate MoveMethod;
}

public class B
{
  public static void MoveIt(object o)
  {
    // Do something
  }    
}

public class C
{
  public void Assign()
  {
    A.MoveMethod = B.MoveIt;
  }

  public void DoSomething()
  {
    if (A.MoveMethod!=null)
      A.MoveMethod(new object()); 
  }
}

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

public delegate void BoringDelegate();


internal class Bar {
    public static BoringDelegate NoOp;
    static Bar() {
        NoOp = () => { };
    }
}

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

как только вы объявили своего делегата как:

public delegate void MoveDelegate (Actor sender, MoveDirection args);

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


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

однако я бы предпочел использовать интерфейс вместо делегата raw.

рассмотрим следующий пример:

public interface IGameStrategy {
    void Move(Actor actor, MoveDirection direction);
}

public class ConsoleGameStrategy : IGameStrategy {
    public void Move(Actor actor, MoveDirection direction)
    {
        // basic console implementation
        Console.WriteLine("{0} moved {1}", actor.Name, direction);
    }
}

public class Actor {
    private IGameStrategy strategy; // hold a reference to strategy

    public string Name { get; set; }    

    public Actor(IGameStrategy strategy)
    {
        this.strategy = strategy;
    }

    public void RunForrestRun()
    {
        // whenever I want to move this actor, I may call strategy.Move() method

        for (int i = 0; i < 10; i++)
            strategy.Move(this, MoveDirection.Forward);
    }
}

в вызывающем коде:

var strategy = new ConsoleGameStrategy();

// when creating Actors, specify the strategy you want to use
var actor = new Actor(strategy) { Name = "Forrest Gump" };
actor.RunForrestRun(); // will write to console

Это похоже по духу на разработка стратегии шаблон и позволяет отделить Actor движение от фактической реализации стратегия (консоль, графика, что угодно). Позже могут потребоваться другие методы стратегии,что делает его лучшим выбором, чем делегат.

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


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

public delegate void MoveDelegate (Actor sender, MoveDirection args);

public static MyClass
{
     public static MoveDelegate MoveDelegateInstance;
}

public static delegate void MoveDelegate (Actor sender, MoveDirection args);

позвольте мне рассказать вам, что произошло, когда вы объявили делегата

компилятор создает класс с именем MoveDelegate, и расширяет его с помощью System.MulticastDelegate.

Так как вы не можете расширить любой нестатический тип статическим типом.

Так вот почему компилятор не разрешает статическое объявление делегата. Но все же вы можете иметь статическую ссылку делегата.