[英]Noobie Delegate Fundamentals C#
我不认为我理解委托方法的要点。 我见过的所有例子都是这样的:
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()会做....
有人可以解释一下吗? 非常感谢!
delegate
很有用,因为它实际上充当占用string
,用于将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));
我不明白为什么只需要实现一个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"));
同样,我们只需要编写与我们特定需求相关的代码,而不是复制遍历我们的集合并计算项目所需的所有样板代码......
在插图中使用委托可以更改方法的实现。
更好的例子是Comparer方法。 我不会进入IComparer
接口,但足以说明,使用委托,您可以通过将委托传递给比较函数来修改排序方法的行为。
http://msdn.microsoft.com/en-us/library/system.collections.icomparer.aspx
首先,它允许您使用相同的方法签名注入不同的行为。 在一种情况下,您可能只想添加到列表中。 在另一种情况下,您可能希望添加到列表并写入日志文件,或者您可能想要在DoSomethingToStringsDelegate
执行的任何其他操作。
从事件的角度来考虑它。 假设您有一个对项目列表进行一些处理的类,并且对于每个项目,消费您的类的人可能希望被通知项目已被处理(可能更新进度条,或更新系统的其他部分) , 随你)。 让我们把代表放在一边,让我们看看如何使用接口实现这一点:
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并过滤集合)或者像我已经演示过的回调/事件以上。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.