使用委托在运行时选择功能

时间:2016-02-05 10:34:39

标签: c# delegates

我是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()。

如果我只想调用其中一种方法并且决定是在运行时做出怎么办?

我可能会遗漏一些非常小的东西,但代表们真的很难理解。

2 个答案:

答案 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();
}

也就是说,某个方法无法有条件地与其他方法切换,但您需要使用常规控制流程块(如ifswitch)来决定

为了不重复Jon Skeet的回答,我将添加另一种可能的解决方案:

    string text = "";

    sampleDelegate s1 = () =>
    {
         if(!string.IsNullOrEmpty(text)) 
         {
             SampleMethod1();
         }
         else
         {
             SampleMethod2();
         }
    };

    s1();

检查,而不是创建两个sampleDelegate实例,您可以创建处理条件逻辑的实例,以调用SampleMethod1SampleMethod2

整个() => { }事件称为匿名委托

它也可以表达如下:

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

您可以通过DoStuffDoStuff("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));
}