Делегировать к методу экземпляра не может иметь значение null - PullRequest
10 голосов
/ 20 сентября 2010

Я занимаюсь разработкой приложения на 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 »». Что я делаю не так?

Ответы [ 5 ]

11 голосов
/ 20 сентября 2010

Вам необходимо назначить допустимую функцию (размещенную в некотором классе в динамически загружаемой 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;
    }
}
10 голосов
/ 20 сентября 2010

В вашей строке:

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

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

4 голосов
/ 20 сентября 2010

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

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

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
    }
}
3 голосов
/ 20 сентября 2010

Джим, я пытаюсь изучать делегатов в C # самостоятельно.

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

В строке:

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));
  }
}
2 голосов
/ 20 сентября 2010

Вы пытаетесь инициализировать делегата для вызова самого себя. То, что вы делаете в принципе, не имеет смысла.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...