Параметры метода кажутся динамическими, не уверен, как это работает - PullRequest
1 голос
/ 27 марта 2009

Если у меня есть делегат и метод

public delegate void SomeDelegate(String p);

void aMethod(String p) {
}

А потом я пытаюсь вызвать это в новой теме, например

SomeDelegate sd = new SomeDelegate(aMethod());
sd.BeginInvoke("heyhey", callBack, null)

Вызов метода BeginInvoke теперь принимает строку в качестве первого параметра, однако, если я удалю «String p» из делегата и aMethod (), BeginInvoke теперь требует только два параметра.

Как мне создать такую ​​функцию, как BeginInvoke, которая динамически принимает различные типы параметров на основе кода в другом месте?

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

Ответы [ 5 ]

4 голосов
/ 27 марта 2009

Я думаю, что вам не хватает того факта, что методы Invoke / BeginInvoke / EndInvoke не определены в Delegate - они автоматически генерируются компилятором для типа делегата.

Когда вы первоначально объявляете

public delegate void SomeDelegate(String p);

компилятор генерирует:

public class SomeDelegate : Delegate
{
    public SomeDelegate(Object target, IntPtr method) { ... }

    public virtual IAsyncResult BeginInvoke(string p, 
        AsyncCallback callback, object @object) { ... }

    public virtual void EndInvoke(IAsyncResult result) { ... }

    public virtual void Invoke(string p) { ... }
}

(с соответствующими телами методов, атрибутами и т. Д.).

Когда вы изменяете подпись SomeDelegate для удаления параметра, сгенерированный тип меняется на:

public class SomeDelegate : Delegate
{
    public SomeDelegate(Object target, IntPtr method) { ... }

    public virtual IAsyncResult BeginInvoke(
        AsyncCallback callback, object @object) { ... }

    public virtual void EndInvoke(IAsyncResult result) { ... }

    public virtual void Invoke() { ... }
}

На самом деле ничего динамичного не происходит - вы изменили подпись SomeDelegate, и это изменило подпись SomeDelegate.BeginInvoke. Ничего загадочного.

2 голосов
/ 27 марта 2009

Я считаю, что Intellisense выполняет свою работу для делегатов.

Возможно, вы могли бы определить метод с помощью ключевого слова params , чтобы метод принимал переменное количество параметров, но пока не выпущен C # 4.0 (он имеет необязательные и именованные параметры), я не уверен Вы можете делать такие вещи самостоятельно.

Конечно, я могу ошибаться.

0 голосов
/ 29 апреля 2009

Это не то, что вы можете сделать. Вы не так мощны, как компилятор!

0 голосов
/ 27 марта 2009

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

public delegate void SomeDelegate(String p, string q);
private static void aMethod(string p, string q) 
{
    Console.WriteLine(p + q);
}

и использовать делегата:

SomeDelegate sd = new SomeDelegate(aMethod);
sd.BeginInvoke("heyhey", "yoyo" callback, null);

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

ThreadPool.QueueUserWorkItem(delegate { aMethod("heyhey", "yoyo"); });
0 голосов
/ 27 марта 2009

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

EDIT:

Тогда я, наверное, неправильно понял ваш вопрос.

Если вы ищете, как принимать различные параметры без перегрузки, используйте:

public void MyMethod(params object[] args)
{
  foreach (object o in args)
  {
    Type t=o.GetType();
    // do something with o depending on the type
    if (t==typeof(int))
    {
      int i=(int)o; 
      // ...
    }
    else if (t==typeof(string)) // etc.
    {
    }
  }
}

Затем вы можете позвонить:

MyMethod(5, "foo", 7.77);
MyMethod("foo", "bar");
// etc.
...