C# - 有人能告诉我为什么以及在哪里使用代表?

时间:2009-01-29 12:19:42

标签: c# delegates

我认为我理解C#中委托的概念作为指向方法的指针,但是我找不到任何好的例子来说明使用它们的好主意。有哪些例子要么代表更优雅/更好,要么使用其他方法无法解决?

12 个答案:

答案 0 :(得分:11)

.NET 1.0代理:

this.myButton.Click += new EventHandler(this.MyMethod);

.NET 2.0委托:

this.myOtherButton.Click += delegate {
    var res = PerformSomeAction();
    if(res > 5)
        PerformSomeOtherAction();
};

它们似乎很有用。怎么样:

new Thread(new ThreadStart(delegate {
    // do some worker-thread processing
})).Start();

答案 1 :(得分:6)

我主要用于简单的异步编程。使用委托开始一个方法开始...方法非常简单,如果你想解雇和忘记。

当接口不可用时,代理也可以像一样使用接口。例如。从COM类,外部.Net类等调用方法。

答案 2 :(得分:6)

代表们究竟是什么意思?以下是两种使用方式:

void Foo(Func<int, string> f) {
 //do stuff
 string s = f(42);
 // do more stuff
}

void Bar() {
 Func<int, string> f = delegate(i) { return i.ToString(); } 
//do stuff
 string s = f(42);
 // do more stuff
}

第二个问题的一点是,您可以作为代表动态声明新功能。这可以在很大程度上被lambda表达式取代,并且只要你想要一小段逻辑1)传递给另一个函数,或者2)重复执行,它就很有用。 LINQ就是一个很好的例子。每个LINQ函数都使用lambda表达式作为参数,指定行为。例如,如果您有List<int> l,那么l.Select(x=>(x.ToString())将在列表中的每个元素上调用ToString()。我写的lambda表达式是作为委托实现的。

第一个案例显示了如何实施Select。你将一个代表作为你的论点,然后在需要时调用它。这允许调用者自定义函数的行为。再次以Select()为例,函数本身保证传递给它的委托将在列表中的每个元素上调用,并返回每个元素的输出。该代表实际做什么取决于您。这使它成为一种非常灵活和通用的功能。

当然,它们也用于订阅活动。简而言之,委托允许您引用函数,将它们用作函数调用中的参数,将它们分配给变量以及您想要做的任何其他事情。

答案 3 :(得分:4)

事件是最明显的例子。比较在Java(接口)和C#(委托)中实现观察者模式的方式。

此外,很多新的C#3功能(例如lambda表达式)都基于代理,并进一步简化了它们的使用。

答案 4 :(得分:3)

例如在多线程应用中。如果你想让几个线程使用一些控件,你应该使用委托。对不起,代码在VisualBasic中。

首先声明一个委托

Private Delegate Sub ButtonInvoke(ByVal enabled As Boolean)

编写一个函数来启用/禁用多个线程的按钮

Private Sub enable_button(ByVal enabled As Boolean)
    If Me.ButtonConnect.InvokeRequired Then

        Dim del As New ButtonInvoke(AddressOf enable_button)
        Me.ButtonConnect.Invoke(del, New Object() {enabled})
    Else
        ButtonConnect.Enabled = enabled
    End If

End Sub

答案 5 :(得分:2)

我一直使用LINQ,尤其是lambda表达式,以提供评估条件或返回选择的函数。还可以使用它们来提供比较两个项目进行排序的功能。后者对于通用集合非常重要,因为默认排序可能适合也可能不适合。

   var query = collection.Where( c => c.Kind == ChosenKind )
                         .Select( c => new { Name = c.Name, Value = c.Value } )
                         .OrderBy( (a,b) => a.Name.CompareTo( b.Name ) );

答案 6 :(得分:2)

Delegates的一个好处是异步执行。

当您异步调用方法时,您不知道它何时将完成执行,因此您需要将委托传递给该方法,该方法指向在第一个方法完成执行时将调用的另一个方法。在第二种方法中,您可以编写一些代码来通知您执行已完成。

答案 7 :(得分:2)

技术委托是一种用于封装具有特定签名和返回类型的方法的引用类型

答案 8 :(得分:1)

其他一些评论触及了异步世界...但我还是会发表评论,因为我最喜欢这样做的“味道”:

ThreadPool.QueueUserWorkItem(delegate
{
    // This code will run on it's own thread!
});

此外,代表们的一个重要原因是“CallBacks”。假设我做了一些功能(异步),你想让我调用一些方法(让我们说“AlertWhenDone”)......你可以将“委托”传递给你的方法,如下所示:

TimmysSpecialClass.DoSomethingCool(this.AlertWhenDone);

答案 9 :(得分:1)

除了你可能熟悉的事件中的角色之外,如果你使用了winforms或asp.net,代表对于使类更灵活(例如在LINQ中使用它们的方式)非常有用。

“寻找”事物的灵活性非常普遍。你有一系列的东西,你想提供一种找东西的方法。您现在可以允许调用者提供算法,以便他们可以搜索您认为合适的集合,而不是猜测某人可能想要查找的每种方式。

这是一个简单的代码示例:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Delegates
{
    class Program
    {
        static void Main(string[] args)
        {
            Collection coll = new Collection(5);
            coll[0] = "This";
            coll[1] = "is";
            coll[2] = "a";
            coll[3] = "test";

            var result = coll.Find(x => x == "is");

            Console.WriteLine(result);

            result = coll.Find(x => x.StartsWith("te"));

            Console.WriteLine(result);

    }

}

public class Collection
{
    string[] _Items;

    public delegate bool FindDelegate(string FindParam);

    public Collection(int Size)
    {
        _Items = new string[Size];

    }

    public string this[int i]
    {
        get { return _Items[i]; }
        set { _Items[i] = value; }
    }

    public string Find(FindDelegate findDelegate)
    {
        foreach (string s in _Items)
        {
            if (findDelegate(s))
                return s;
        }
        return null;
    }

}
}

<强>输出

测试

答案 10 :(得分:0)

没有任何delgates会解决其他方法无法解决的问题,但它们提供了更优雅的解决方案。

使用委托,只要具有所需的参数,就可以使用任何功能。

替代方案通常是在程序中使用一种自定义构建的事件系统,创建额外的工作和更多的区域以防止蠕虫进入

答案 11 :(得分:0)

在处理对数据库的外部调用时使用委托是否有优势?

例如可以编码A:

static void Main(string[] args) {

           DatabaseCode("test");

}

public void DatabaseCode(string arg) {

           .... code here ...

}

在代码B中得到改进:

static void Main(string[] args) {

           DatabaseCodeDelegate slave = DatabaseCode;
           slave ("test");

}

public void DatabaseCode(string arg) {

           .... code here ...

}
public delegate void DatabaseCodeDelegate(string arg);

这似乎是主观的,但是存在强烈矛盾的观点?