我想我理解C#中委托的概念作为指向方法的指针,但是我无法找到任何使用它们的好主意的好例子。什么是一些例子,或者更好或更好的委托或不能用其他方法解决?C# - 有人能告诉我为什么和我应该在哪里使用代表?
回答
究竟你代表是什么意思?这里有两种方法可以使用它们:
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()为例,函数本身保证传递给它的委托将在列表中的每个元素上被调用,并且每个元素的输出将被返回。那个代表实际上确实取决于你。这使得它变得非常灵活和一般的功能。
当然,他们也用于订阅活动。简而言之,代表允许您引用函数,在函数调用中将它们用作参数,将它们分配给变量以及您喜欢做的任何其他操作。
我主要使用简单的异步编程。开始使用代表的方法Begin ...方法非常简单,如果你想开火并忘记。
代理也可以使用如接口不可用时的接口。例如。调用COM类的方法,外部.Net类等。
这里没有任何东西可以解决其他方法无法解决的问题,但它们提供了更优雅的解决方案。
对于代表,只要具有所需的参数,可以使用任何函数。
另一种方法是经常使用的一种定制事件系统的程序,创建错误额外的工作和更多的领域中
的.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();
这简直太棒了!了解 – SMUsamaShah 2014-05-12 23:22:06
事件是最明显的例子。比较观察者模式在Java(接口)和C#(委托)中的实现方式。另外,很多新的C#3功能(例如lambda表达式)都基于委托并进一步简化了它们的使用。
例如在多线程应用程序中。如果你想要几个线程使用一些控制,你可以使用代表。对不起,代码是在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表达式启用/禁用按钮,提供评估条件或返回选择的函数。也可以使用它们来提供一个函数,将比较两个项目进行排序。后者对于默认排序可能适用或不适用的泛型集合非常重要。
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));
委托的好处之一是异步执行。
当您异步调用某个方法时,您不知道它何时会完成执行,因此您需要将委托传递给该方法,该方法指向另一个将在第一个方法完成执行时调用的方法。在第二种方法中,您可以编写一些代码来通知您执行已完成。
其他一些评论谈到了异步世界......但自从做这样的我最喜欢的“味道”已经提到无论如何,我会发表评论:
ThreadPool.QueueUserWorkItem(delegate
{
// This code will run on it's own thread!
});
此外,与会代表了巨大的原因是为了“回调”。比方说,我做了一点功能(异步),你要我打电话给一些方法(假设“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;
}
}
}
输出
是
测试
技术上委托是用于封装具有特定签名的方法和返回类型
是否有与外部调用数据库打交道时,使用委托的优势,引用类型?
例如可以代码:
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);
看来,这是主观的,但其中也有很强的相互矛盾的观点的区域?
天哪,我在一年前问过这个问题,现在很难想象代表/ lambda表达式之前的生活!我不得不说,这里的答案仍然是网上最好的例子。这就是SO的力量。 – Alex 2009-12-29 16:39:59