我正在努力理解代表,为此我为自己创建了一个简单的例子,但它没有按照我想要的方式工作,这是我的例子:
我的职能:
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函数中执行它,这是否可以与委托一起使用?
答案 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();
}