Делегировать к методу экземпляра не может иметь нуль 'this'

Я занимаюсь разработкой приложения на C # .NET 2.0, в котором во время выполнения загружается одна из двух библиотек DLL в зависимости от среды. Обе библиотеки DLL содержат одинаковые функции, но они не связаны с одним и тем же смещением адреса. Мой вопрос касается делегатов функций в моем коде приложения.

public class MyClass
{
    public delegate int MyFunctionDelegate(int _some, string _args);

    public MyFunctionDelegate MyFuncToCallFrmApp;

    public MyClass() : base()
    {
        this.MyFuncToCallFrmApp = new MyFunctionDelegate(this.MyFuncToCallFrmApp); // <-- Exception thrown here.
    }

    public SomeFunction()
    {
        MyFuncToCallFrmApp(int _someOther, string _argsLocal);
    }
}

Когда мой код выполняется, я получаюArgumentException делегата для метода экземпляра не может иметь значение «this». Что я делаю неправильно?

 JohnB20 сент. 2010 г., 20:35
@Jon: Хорошо, я согласен с тобой. Например, может быть, у него просто проблемы с пониманием делегатов. Я тоже изо всех сил пытаюсь понять их.
 Jon Skeet20 сент. 2010 г., 20:19
@JohnB: Я хочу знать, чего пытается достичь ОП. Нет никаких указаний относительно того, что он хочет, чтобы эта линия делала. Если он может это объяснить, мы можем попытаться решить, что делать.
 JohnB20 сент. 2010 г., 21:18
9 из ваших 13 ответов - это ответы на ваши собственные вопросы, и я не верю, что они являются лучшими ответами (IMO).
 Jon Skeet20 сент. 2010 г., 17:18
Чего вы ожидаете достичь в теле конструктора?

Ответы на вопрос(5)

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

Вам нужно инициализировать делегат, используя метод из вашего класса, который имеет соответствующий список аргументов в качестве вашего делегата, или не инициализировать делегат и позволить потребителю вашего класса инициализировать делегат, используя соответствующий метод из своего кода (что делегаты обычно используются для:

public class MyClass
{
    public delegate int MyFunctionDelegate(int some, string args);
    public MyFunctionDelegate MyFuncToCallFrmApp;

    public MyClass() : base() { }
    public SomeFunction()
    {
        if(MyFuncToCallFrmApp != null)
            MyFuncToCallFrmApp(_someOther, _argsLocal);
    }
}

public class Consumer
{
    MyClass instance = new MyClass();

    public Consumer()
    {
        instance.MyFuncToCallFrmApp = new MyFunctionDelegate(MyFunc);
    }

    public void MyFunc(int some, string args)
    {
        // Do Something
    }
}

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

В соответствии:

this.MyFuncToCallFrmApp = new MyFunctionDelegate(this.MyFuncToCallFrmApp);

this.MyFuncToCallFrmApp является делегатом, но вместо этого он должен быть корректным обработчиком метода.

Вот как вы переходите в обработчик метода:

public delegate int MyFunctionDelegate(int _some, string _args);

MyFunctionDelegate MyFuncToCallFrmApp = new MyFunctionDelegate(PrintValues);

// the method I'm mapping has a valid signature for the delegate I'm mapping to:
public void PrintValues(int some, string args)
{
  Console.WriteLine(string.Format("Some = {0} & Args = {1}", some.ToString(), args));
}

Надеемся, что ссылка ниже и пример кода будут вам полезны:

Учебник для делегатов

Делегат в C # похож на указатель на функцию в C или C ++. Использование делегата позволяет программисту инкапсулировать ссылку на метод внутри объекта делегата. Затем объект делегата может быть передан в код, который может вызывать ссылочный метод, без необходимости знать во время компиляции, какой метод будет вызван. В отличие от указателей на функции в C или C ++, делегаты являются объектно-ориентированными, безопасными по типу и безопасными. (MSDN)
public class MyClass
{
  // a delegate by definition is a collection of pointers to method handlers
  // I declare my delegate on this line
  // PLEASE NOTE THE SIGNATURE!
  public delegate void MyFunctionDelegate(int some, string args);

  public MyClass() : base()
  {
    // instantiate the delegate (AKA create the pointer)
    MyFunctionDelegate myFunctionDelegate = new MyFunctionDelegate();

    // map a valid method handler (WITH THE SAME SIGNATURE) to this delegate
    // I'm using "+=" operator because you can add more than one handler to a collection
    myFunctionDelegate += new MyFunctionDelegate(PrintValues);

    // invoke the method handler (which in this case is PrintValues() - see below)
    // NOTE THE SIGNATURE OF THIS CALL
    myFunctionDelegate(1, "Test");
  }

  // this is the handler method that I am going to map to the delegate
  // AGAIN, PLEASE NOTE THE SIGNATURE
  public void PrintValues(int some, string args)
  {
    Console.WriteLine(string.Format("Some = {0} & Args = {1}", some.ToString(), args));
  }
}
Решение Вопроса

лассе в динамически загружаемой dll) для вашей переменной делегата. Если функции являются статическими методами на классах сто же имяэто просто:

public MyClass() {
    this.MyFuncToCallFrmApp = ExternalClass.Function;
}

Если функции являются методами экземпляров классов с одинаковыми именами, просто создайте экземпляр и сделайте то же самое (также обратите внимание, что, пока делегат находится в области действия, это предотвратитExternalClass экземпляр из сборки мусора - вы можете захотеть сохранить экземпляр как переменную-член, чтобы сделать это более понятным):

public MyClass() {
    this.MyFuncToCallFrmApp = new ExternalClass().Function;
}

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

public MyClass() {
    if (this.defaultAssembly) {
        this.MyFuncToCallFrmApp = ExternalClass1.Function;
    } else {
        this.MyFuncToCallFrmApp = ExternalClass2.Function;
    }
}

что вы делаете в принципе, не имеет смысла.

this.MyFuncToCallFrmApp = new MyFunctionDelegate(this.MyFuncToCallFrmApp); 

Вы используете «this.MyFuncToCallFrmApp» перед тем, как назначить его, что означает, что он является нулевым во время назначения. Указывать делегату на себя не имеет смысла. Это то, что вы пытаетесь сделать?

Ваш ответ на вопрос