C#代表真实世界用法

我之前曾问过一个关于代表的问题,是否有人必须拥有必须拥有的情况,我必须使用委托? 这如何改善我的C#代码?

就像我使用它的许多场景一样,我似乎总是可以围绕它编程。

假设你不是在谈论事件 – 当然你可以围绕它进行编程。 关键是要让它更好更清洁

protected void Sort() { foreach (string key in _dBase.Keys) { Array.Sort>>(_dBase[key], new Comparison>>( delegate(Pair> a, Pair> b) { if (a == null && b != null) return 1; else if (a != null && b == null) return -1; else if (a == null && b == null) return 0; else return a.First.CompareTo(b.First); })); } } 

没有内联代表我可以这样做吗? 当然。 我的类中是否有一个只用于这个实例的软盘私有方法? 对。

编辑:如评论中所述,您可以简化:

 Array.Sort>>(_dBase[key], new Comparison>>( delegate(Pair> a, Pair> b) { 

 Array.Sort>>(_dBase[key], (a,b) => { 

每当您使用策略模式或观察者模式时,委托使您的工作比使用接口更容易。

如果您想象没有委托的C#,您通常会遇到使用一种方法拥有类或接口的情况。 该方法的名称是多余的。 例如

 public interface IGetMail { Mail JustGetTheMail(); } 

界面就是那个方法。 对该类型的对象的引用实际上只不过是对单个可调用方法的引用。 调用代码:

 Mail m = getMail.JustGetTheMail(); 

可以简化为:

 Mail m = getMail(); 

编译器可以将其作为“语法糖”而没有任何歧义,因为只有一种方法可以调用getMail引用。

所以让我们将这个function添加到我们的C#编译器中。 现在,在声明这些类型时,我们也可以使它更整洁。 调用它时我们不需要指定方法名称,那么为什么我们必须首先给该方法命名?

让我们选择一个标准方法名称Invoke ,即

 public interface IGetMail { Mail Invoke(); } 

我们将添加更多的语法糖,以便我们将其写为:

 public delegate Mail GetMail(); 

嘿presto。 我们已经将代理添加到我们的C#编译器中。

(从技术上讲,CLR也知道代理,因此C#编译器不是生成接口,而是生成一种特殊的“委托”类型,它支持异步调用,并操纵不可变的委托列表并将它们作为单个引用处理;但是在基本forms中,它可以通过接口完成。有人建议为Java做这件事。

然后我们可以进一步添加匿名委托 – 使它们简洁,以接口不是这样的方式实现。

所以要回答你的问题 – 任何时候你的界面有一个方法,它可能是一个委托,你将能够认真减少你必须编写的垃圾代码的数量。

没有人提到这一点,但如果你使用LINQ和Lambda,你总是使用匿名方法。 哪些技术上仍然是代表

假设你有一个名为Person的类

 class Person { public string FirstName { get; set; } public string LastName { get; set; } } 

并且您希望实现一种find方法,您可以根据其FirstName找到该人

 public Person Where(List list, string firstName) { //find the string foreach(Person item in list) if(item.FirstName.Equals(firstName)) return item; } 

这是一个非常具体的搜索,而不是非常动态,这意味着如果您想通过LastName进行搜索,则必须更改此方法或编写新方法。

幸运的是LINQ提供了一个名为Where的扩展方法,你需要传递一个委托 ,你可以借助匿名方法动态创建委托

例如

 string searchString = "Stan"; list.Where( person => person.FirstName.Equals(searchString)); 

但如果您想更改为按LastName搜索,您只需执行此操作即可

 string searchString = "R"; list.Where( person => person.LastName.Equals(searchString)); 

这个例子可能不是你想要的,但我只是想表明,有时我们一直使用代理而不考虑它或实现它。

真实世界用法:

  1. 假设您有一个名为Checker的简单用户控件 – 它只包含2个复选框 – chkA和chkB。
  2. 在用户控件中,您可以通过实现chkA和ChkB的相应事件来控制检查/取消选中事件

3.现在,在一个新的Win Form中,当你拖入Checker时 ……你的目标是确保在点击chkA时你必须改变标签的背景颜色…… lblColorPicker。

请注意,lblColorPicker是一个存在于表单中的控件,并不直接绑定到Checker

你将如何实现这一目标?

回答:

  1. 首先,您必须为用户控件Checker创建一个新事件。
  2. 要创建这个新事件,首先要在用户控件中创建一个委托,然后使用此委托作为您正在编写的新事件的定义类型。
  3. 然后,此事件必须映射到用户控件中的chkA …事件。

通过这种方式,您可以通过引用事件来控制chkA …来自任何新表单…通过您刚刚编写的委托。

所以,真实世界的使用!

在编写代表时无法实现此目标。

如果您不这么认为,请告诉我……或者您是否需要更多详细说明。

在某些情况下,匿名委托使代码更具可读性(您不必转到另一种方法来查看属于您的方法的代码:

Winforms示例

 class MyForm:Form{ //... protected override void OnLoad(EventArg e){ this.Cursor=Cursors.Wait(); this.Enabled=false; // do a long running DB operation without blocking the UI Thread ThreadPool.QueueUserWorkItem(state=>{ DoLongDBOperation(); // re enable the form BeginInvoke(new Action(()=>{ this.Cursor=Cursors.Default;this.Enabled=true;})); }); } 

如果你向你的class级添加事件或做任何不正常的事情(代表们还有其他几个很好的理由),代表是绝对必须拥有的。 好处是它是一种非常灵活的方法。

我想你指的是定义自定义代理?

EventHandler最小化了对自定义委托定义的要求,但如果要向方法签名添加其他参数,它们仍然很有用。

每当您需要修改或更改winForms控件的任何属性时,您需要使用委托将控制权传递回创建控件的线程…仅举几个例子中的一个。

一个例子是发布/订阅消息调度程序。 您需要向调度程序注册事件,然后适当地调用它们。 这使您可以非常轻松地连接不同的代码片段。 没有使用代表,我想不出办法做到这一点

假设您有一个响应不同按键的控制台应用程序:

  Action a = () => {/* Do Stuff*/}; Action b = () => {/* Do Stuff*/}; Action c = () => {/* Do Stuff*/}; Action d = () => {/* Do Stuff*/}; Action e = () => {/* Do Stuff*/}; Action f = () => {/* Do Stuff*/}; Action g = () => {/* Do Stuff*/}; Action h = () => {/* Do Stuff*/}; Action i = () => {/* Do Stuff*/}; Action j = () => {/* Do Stuff*/}; List actions = new List() {a,b,c,d,e,f,g,h,i,j}; string line; while((line = Console.ReadKey().KeyChar) != 'q') { if(line.isBetween_0_and_9()) { actions[line.ParseInt()](); } } 

显然你可以使用一堆Ifs,但这不仅更容易,而且几乎可以肯定更清晰/可读。