我是C#的新手,仍然了解代表的概念。我所知的代理是委托定义了一个函数签名,具有相同签名的函数可以添加到该委托中。
public class ss
{
public delegate void sampleDelegate();
public ss()
{
sampleDelegate s1 = new sampleDelegate(sampleMethod);
s1+= new sampleDelegate(sampleMethod2);
s1();
}
public static void sampleMethod()
{
}
public static void sampleMethod2()
{
}
}
在上面的代码中,我创建了一个委托,并给它sampleMethod和sampleMethod2。当我调用s1()时,它调用sampleMethod()和sampleMethod2()。
如果我只想调用其中一种方法并且决定是在运行时做出怎么办?
我可能会遗漏一些非常小的东西,但代表们真的很难理解。
答案 0 :(得分:2)
如果我只想调用其中一种方法并在运行时做出决定该怎么办?
然后你基本上不把它们组合在一起。例如:
// Names changed to be more conventional
SampleDelegate s1 = someCondition
? new SampleDelegate(SampleMethod)
: new SampleDelegate(SampleMethod2);
// This will call either SampleMethod or SampleMethod2, depending on condition
s1();
请注意,通常我会使用方法组转换,但不能将方法组用于条件运算符的第二个和第三个操作数。你可以使用:
SampleDelegate s1;
if (condition) {
s1 = SampleMethod;
} else {
s2 = SampleMethod2;
}
......或
SampleDelegate s1 = someCondition
? new SampleDelegate(SampleMethod)
: SampleMethod2;
但这些看起来都不是特别好。
答案 1 :(得分:0)
委托就像指向方法的指针。在运行时,除了方法是对象的成员之外,没有什么可以区分调用委托或方法:
some.Method();
someDelegate();
委托的目标是创建一个 blackbox ,您希望某些代码能够放置某些行为,而您只需依赖方法签名。
在一天结束时,他们喜欢方法接口:
// It must be a parameterless method which returns no value
public delegate void Action();
// vs
// It must be a class which implements a parameterless method "Do"
// which returns no value
public interface Action
{
void Do();
}
也就是说,某个方法无法有条件地与其他方法切换,但您需要使用常规控制流程块(如if
或switch
)来决定做
为了不重复Jon Skeet的回答,我将添加另一种可能的解决方案:
string text = "";
sampleDelegate s1 = () =>
{
if(!string.IsNullOrEmpty(text))
{
SampleMethod1();
}
else
{
SampleMethod2();
}
};
s1();
检查,而不是创建两个sampleDelegate
实例,您可以创建处理条件逻辑的实例,以调用SampleMethod1
或SampleMethod2
。
整个() => { }
事件称为匿名委托。
它也可以表达如下:
string text = "";
sampleDelegate s1 = delegate()
{
if(!string.IsNullOrEmpty(text))
{
SampleMethod1();
}
else
{
SampleMethod2();
}
};
但是不要使用上面的语法......它来自旧的.NET时代(.NET 1.0 / 1.1 / 2.0)。
总之,委托可以或不可以作为实际的类方法提供,但您可以将类方法与匿名委托结合起来以满足您的需求。
如果我只想调用其中一种方法并做出决定,该怎么办? 要在运行时制作?我可能会错过很小的东西但是 代表们真的很难理解。
实际上这是使用代理人的理由,但是当你说你错过某些东西时,你就是对的。
代表习惯于以下情况:
public void DoStuff(string text, Func<string, string> textFormatter = null)
{
Console.WriteLine(textFormatter != null ? textFormatter(text) : text);
}
您可以通过DoStuff
或DoStuff("hello world")
这样的方式致电DoStuff("hello world", text => $"<strong>{text}</strong>")
。
DoStuff
方法实现不知道如何格式化给定文本,并且您提供了一个可选参数,以将委托作为参数,将接收要格式化的整个文本,并且它将返回格式化文本。
毕竟,这不是条件吗?基于调用者,DoStuff
以自定义方式格式化文本。您甚至可以提供默认格式:
public void DoStuff(string text, Func<string, string> textFormatter = null)
{
// We'll give a default formatter if none is provided ;)
if(textFormatter == null)
textFormatter = text => $"<span>{text}</span>";
Console.WriteLine(textFormatter(text));
}