我不认为我理解委托方法的要点。我见过的所有例子都是这样的:
class DelegateClass
{
private List<string> ListString = new List<string>;
delegate void DoSomethingToStringsDelegate(string s);
public base()
{
ListString.Add("string"); ....
}
void ProcessStrings(DoSomethingToStringsDelegate dstsd)
{
foreach(string s in ListString)
dstsd(s);
}
}
class AClass
{
...
void UseDelegateMethod(...)
{
DelegateClass ds = new DelegateClass();
ds.ProcessStrings(new DoSomethingToStringsDelegate(PrintStrings);
}
void PrintStrings(string s)
{
System.out.Write(s);
}
}
我不明白为什么只需要实现一个getListStrings()并自己遍历字符串,执行你需要做的事情,就好像它是一个委托一样。
foreach( string s in ds.ggetListStrings() )
System.out.Write(s);
私人会员的理由没有意义,因为我可以这样做:
global List<Strings> myListStrings = new List<Strings>();
ds.ProcessStrings(new DoSomethingToStringsDelegate(GetStrings);
void GetStrings(string s)
{
myListStrings.Add(s);
}
...现在我有相同的列表,就像getListStrings()一样......
有人可以解释一下吗?非常感谢!
答案 0 :(得分:4)
delegate
非常有用,因为它实际上充当了以string
作为参数并返回void
的任何方法的占位符。
如果您熟悉C,它与函数指针的工作方式类似。在它的位置,您可以传递任何匹配签名和返回类型的方法。
例如,假设我想实现一个对一组对象进行排序的方法。除了对象列表,我还可以传递一个委托,指示如何完成排序。由于任何匹配委托的方法都可以传递,我可以在不同的方法之间动态切换,如果我想要减少或增加排序:
delegate int comparisonDelegate(int p1, int p2);
void SortArray(int[] array, comparisonDelegate cmp)
{
// determine order according to cmp
}
int CompareDecreasing(int p1, int p2)
{
if(p1 > p2) return -1;
if(p1 < p2) return 1;
return 0;
}
int CompareIncreasing(int p1, int p2)
{
if(p1 > p2) return 1;
if(p1 < p2) return -1;
return 0;
}
现在我可以将SortArray
称为:
SortArray(array, new comparisonDelegate(compareDecreasing));
SortArray(array, new comparisonDelegate(compareIncreasing));
答案 1 :(得分:3)
我不明白为什么只需要实现一个getListStrings()并自己遍历字符串,执行你需要做的事情就好了,为什么需要这样做,就像它是一个委托一样。
这里的目标是创建一个可以对集合起作用的函数,但是可以进行任何操作。
通过示例更容易理解 - 要查看有用的方法和原因的一个很好的示例,请查看LINQ to Objects。
假设您要查看有多少字符串超过4个字符 - Enumerable.Count方法有一个带有委托的重载 - 可以使用Func<T,bool>
谓词。这允许您指定任何操作并计算元素,即:
List<string> listOfStrings = GetListOfStrings();
int countOfStringsGreaterThanFourChars = listOfStrings.Count(s => s.Length > 4);
在这里,我们传递一个委托(通过lambda表达式创建),它给出了我们的标准。通过使用Count
方法接受委托,它适用于任何标准,因此我们不必在每次想要不同条件时重新实现它。
假设我们想看看有多少字符串以“E”开头,我们可以使用:
int countOfStringsStartingWithE = listOfStrings.Count(s => s.StartsWith("E"));
同样,我们只需要编写与我们特定需求相关的代码,而不是复制循环我们的集合并计算项目所需的所有样板代码...... < / p>
答案 2 :(得分:1)
在插图中使用代理可以更改方法的实现。
更好的例子是Comparer方法。我不会进入IComparer
接口,但足以说明,使用委托,您可以通过将委托传递给比较函数来修改排序方法的行为。
http://msdn.microsoft.com/en-us/library/system.collections.icomparer.aspx
答案 3 :(得分:0)
首先,它允许您使用相同的方法签名注入不同的行为。在一种情况下,您可能只想添加到列表中。在另一种情况下,您可能希望添加到列表并写入日志文件,或者您想要在DoSomethingToStringsDelegate
中执行的任何其他操作。
答案 4 :(得分:0)
从事件的角度来考虑它。假设您有一个对项目列表进行一些处理的类,并且对于每个项目,消费您的类的人可能希望被通知项目已被处理(可能更新进度条,或更新系统的其他部分) , 随你)。让我们把代表放在一边,让我们看看我们如何使用接口来实现它:
public class MyClassThatDoesSomething
{
private List<string> list = new List<string>();
public void ProcessList()
{
foreach(var item in list)
{
ProcessItem(item);
//how do we notify someone here??
}
}
private void ProcessItem(string item){}
}
现在说某人正在消耗这个课程:
var mc = new MyClassThatDoesSomething();
mc.ProcessList(); //how do I know when each one has been processed?
所以解决这个问题,让我们创建一个接口:
public interface IItemProcessed
{
void ItemProcessed(string item);
}
我们现在可以重构我们原来的课程:
public class MyClassThatDoesSomething
{
private List<string> list = new List<string>();
public void ProcessList()
{
foreach(var item in list)
{
ProcessItem(item);
//how do we notify someone here??
if(this.Listener != null)
{
this.Listener.ItemProcessed(item);
}
}
}
private void ProcessItem(string item){}
public IItemProcessed Listener {get;set;}
}
,您班级的消费者现在可以这样做:
public class ProcessListener : IItemProcessed
{
public void ItemProcessed(string item)
{
Console.WriteLine(item);
//update progress bar, whatever
}
}
var mc = new MyClassThatDoesSomething();
mc.Listener = new ProcessListener();
mc.ProcessList();
现在您已了解这一点,您可以将代理视为迷你接口,然后您可以将原始类更改为:
public class MyClassThatDoesSomething
{
private List<string> list = new List<string>();
public void ProcessList()
{
foreach(var item in list)
{
ProcessItem(item);
//how do we notify someone here??
if(this.Callback != null)
{
this.Callback(item);
}
}
}
private void ProcessItem(string item){}
public Action<string> Callback {get;set;}
}
和消费者:
var mc = new MyClassThatDoesSomething();
mc.Listener = s =>
{
Console.WriteLine(s);
//update progress bar, whatever
}
mc.ProcessList();
总而言之,您可以将委托视为向外部人员提供一个简单的“钩子”到您的代码中的方式,以便让它们提供小块逻辑(想想Linq并过滤集合)或者像我这样的回调/事件上面已经证明了这一点。