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

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

代表们究竟是什么意思? 以下是两种可以使用它们的方法:

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

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

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

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

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

.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(); 

我主要使用for easy asynch编程。 使用委托开始一个方法开始…方法如果你想要发射并忘记就很容易。

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

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

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

例如,在multithreading应用程序中。 如果你想让几个线程使用一些控件,你应该使用委托。 对不起,代码在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 

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

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

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

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

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

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

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

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

 TimmysSpecialClass.DoSomethingCool(this.AlertWhenDone); 

除了你可能熟悉的事件之外,如果你使用了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; } } } 

产量

测试

实际上并没有什么能够解决其他方法无法解决的问题,但它们提供了更优雅的解决方案。

对于委托,只要具有所需参数,就可以使用任何function。

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

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

例如可以代码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); 

这似乎是主观的,但这个观点有很强的冲突点?