8

我想我将 C# 中委托的概念理解为指向方法的指针,但我找不到任何好的例子来说明在哪里使用它们是个好主意。有哪些例子对于代表来说更优雅/更好,或者不能使用其他方法解决?

4

12 回答 12

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();
于 2009-01-29T12:24:19.393 回答
6

我主要使用简单的异步编程。使用委托开始一个方法 Begin... 如果你想开火然后忘记,方法真的很容易。

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

于 2009-01-29T12:23:07.617 回答
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> lthenl.Select(x=>(x.ToString())将对列表中的每个元素调用 ToString()。我写的 lambda 表达式是作为委托实现的。

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

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

于 2009-01-29T12:39:38.067 回答
4

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

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

于 2009-01-29T12:26:20.747 回答
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
于 2009-01-29T12:27:26.017 回答
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 ) );
于 2009-01-29T12:27:40.167 回答
2

委托的好处之一是异步执行。

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

于 2009-01-29T12:29:51.457 回答
2

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

于 2009-01-29T13:30:32.770 回答
1

其他一些评论触及了异步世界......但无论如何我都会发表评论,因为我最喜欢这样做的“味道”已经提到:

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

此外,代表的一个重要原因是“回调”。假设我做了一些功能(异步),并且您希望我调用一些方法(例如“AlertWhenDone”)......您可以将“委托”传递给您的方法,如下所示:

TimmysSpecialClass.DoSomethingCool(this.AlertWhenDone);
于 2009-01-29T12:32:27.350 回答
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;
    }

}
}

输出

测试

于 2009-01-29T12:35:26.783 回答
0

确实没有什么可以用其他方法解决的,但它们提供了一个更优雅的解决方案。

使用委托,任何函数都可以使用,只要它具有所需的参数。

另一种方法通常是在程序中使用一种自定义构建的事件系统,从而创造额外的工作和更多的区域让错误潜入

于 2009-01-29T12:23:11.097 回答
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);

这似乎是主观的,但是一个存在强烈冲突观点的领域?

于 2011-01-25T09:49:55.873 回答