方法参数似乎是动态的,不确定这是如何工作的

时间:2009-03-27 05:14:07

标签: c# delegates dynamic-languages

如果我有代表和方法

public delegate void SomeDelegate(String p);

void aMethod(String p) {
}

然后我尝试在一个像这样的新线程上调用它

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

BeginInvoke方法调用现在接受一个字符串作为第一个参数,但是,如果我从委托和aMethod()中删除“String p”,那么BeginInvoke现在只需要两个参数。

如何构建像BeginInvoke这样的函数,根据其他地方的代码动态接受不同类型的参数?

对不起如果我在这里模糊不清,但我以前从未见过这个,我很好奇。

5 个答案:

答案 0 :(得分:4)

我认为您遗失的是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的签名。没什么神秘的。

答案 1 :(得分:2)

我相信Intellisense正在为代表们做这件事。

您可以使用 params 关键字定义一个方法,让方法接受可变数量的参数,但是在C#4.0发布之前(它有可选的和命名的参数),我不是确定你可以自己做这样的事情。

当然,我可能是错的。

答案 2 :(得分:0)

这称为方法重载。您可以找到教程here

编辑:

然后我可能误解了你的问题。

如果您正在查看如何接受不同的参数而不会超载,请使用:

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.

答案 3 :(得分:0)

目前还不清楚自己想做什么。如果您想知道如何使用不同的参数创建新的委托,请按以下方式执行:

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"); });

答案 4 :(得分:0)

这不是你能做的。你没有编译器那么强大!