如何通过C#中的参数委托将两个函数传递给另一个函数

时间:2015-01-04 12:57:01

标签: c# delegates

我正在努力理解代表,为此我为自己创建了一个简单的例子,但它没有按照我想要的方式工作,这是我的例子:

我的职能:

class Functions
{

    public string MyFname(string MyString) 
    {

        return MyString;


    }
    public string MyLname(string MyString)
    {

        return MyString;


    }


}

委托:

class DelClass
{
    public delegate string StrDelegate(string OutPutString);

    public void StringCon(StrDelegate Fname,StrDelegate Lname) 
    {

        Console.WriteLine(Fname + " " + Lname);

    }
}

主:

class Program
{
    static void Main(string[] args)
    {
        DelClass MyDel = new DelClass();
        Functions MyTster = new Functions();
        DelClass.StrDelegate Name = new DelClass.StrDelegate(MyTster.MyFname);
        Name("SomeVariableName");
        DelClass.StrDelegate Family = new DelClass.StrDelegate(MyTster.MyLname);
        Family("SomeVariableFamilyName");
        MyDel.StringCon(Name, Family);

    }
}

问题是控制台窗口没有显示我传递的字符串,而是显示下面提到的文本:

  

MyDelegateMethodInMethod.DelClass + StrDelegate MyDelegateMethodInMethod.DelClass +   StrDelegate

当我尝试在StringCon体中调用传递的函数时:

Console.WriteLine(Fname() + " " + Lname();

编译器抱怨“委托'StrDelegate'不接受0参数”但我不想在StringCon的传递参数中传递参数,我想在我的Main函数中执行它,这是否可以与委托一起使用?

3 个答案:

答案 0 :(得分:7)

委托是包含对方法的引用的对象。调用委托具有执行该方法的效果。您的两个方法都有一个String参数,因此要执行这些方法中的任何一个都会传递一个String参数。这意味着,当您调用代理时,他们需要将单个String参数传递给它们执行的方法。你认为这个价值来自哪里?代表们不会凭空掏空。您必须在调用它时将其传递给委托。在这段代码中:

public void StringCon(StrDelegate Fname,StrDelegate Lname) 
{
    Console.WriteLine(Fname + " " + Lname);
}
你在做什么?你没有。您必须向委托提供参数,以便他们将这些参数提供给方法:

public void StringCon(StrDelegate Fname,StrDelegate Lname) 
{
    Console.WriteLine(Fname("John") + " " + Lname("Doe"));
}

这是一个非常糟糕的示范,因为你的方法并没有真正做任何有用的事情。如何定义一个方法有用这样的东西:

public string GetFullName(string givenName, string familyName)
{
    return givenName + " " + familyName;
}

和相应的代表:

public delegate string FullNameGetter(string givenName, string familyName);

然后像这样调用它:

var fng = new FullNameGetter(GetFullName);

Console.WriteLine(fng("John", "Doe"));

答案 1 :(得分:2)

如果您不想传递字符串作为输入,则应该适当地声明代理:

class DelClass
{
    public delegate string StrDelegate();
    public void StringCon(StrDelegate Fname,StrDelegate Lname) 
    {
        Console.WriteLine(Fname() + " " + Lname());
    }
}

根据您所写的内容,您希望在某处保存字符串属性 - 但委托不是这样做的地方。您可以使用FName,LName属性创建对象:

class Functions
{
    public string MyFname() { return MyFnameProperty; }
    public string MyLname() { return MyLnameProperty; }
    public string MyFnameProperty { get; set; }
    public string MyLnameProperty { get; set; }
}

最后,在Main,你会写:

class Program
{
    static void Main(string[] args)
    {
        DelClass MyDel = new DelClass();
        Functions MyTster = new Functions();
        DelClass.StrDelegate Name = new DelClass.StrDelegate(MyTster.MyFname);
        MyTster.MyFnameProperty ="SomeVariableName";
        DelClass.StrDelegate Family = new DelClass.StrDelegate(MyTster.MyLname);
        MyTster.MyLnameProperty = "SomeVariableFamilyName";
        MyDel.StringCon(Name, Family);
    }
}

答案 2 :(得分:2)

这不是你应该如何使用委托,委托主要用作回调函数,或用于EventHandlers,或者你喜欢调用函数。

EventHandler的一个例子可能是

public delegate void ReportErrorDelegate(object sender, MyCustomEventArgs e);

有一个班级

public class MyCustomEventArgs : EventArgs
{
     // some implementation
     public MyCustomEventArgs() 
     {
     }

     public MyCustomEventArgs(object argument)
         : this()
     {
         ....
     }
}

之后您可以创建一个基于您的委托的事件

public interface IRaiseMyCustomEventArgs
{
     event ReportErrorDelegate CustomEventFired;
}

然后您可以将其实现为

public class RaiseMyCustomEventArgs : IRaiseMyCustomEventArgs
{
     public event ReportErrorDelegate CustomEventFired;

     protected virtual void RaiseCustomEventArgs(object argument)
     {
         var local = CustomEventFired;
         if (local != null) {
             local.Invoke(this, new MyCustomEventArgs(argument));
         }
     }
}

另一个选项可能是在您检测到需要调用UI交互后调用方法,例如

public delegate void SetTextDelegate(TextBox tb, string text);

public void SetText(TextBox tb, string text)
{
     if (tb.InvokeRequired) 
     {
          tb.Invoke(new SetTextDelegate(SetText), tb, text);
          return;
     }
     tb.Text = text;
}

将从在Windows应用程序内运行的线程调用(例如)

public void RunThread() 
{
     // assuming TextBox1 exists on the form
     Thread t = new Thread(() => {
         SetText(TextBox1, "Hello World");
     });
     t.Start();
}