你什么时候在C#中使用委托?

你在C#中使用什么代表?

现在我们在C#中使用了lambdaexpression式和匿名方法,我使用了更多的委托。 在C#1中,你总是必须有一个单独的方法来实现逻辑,使用委托通常没有任何意义。 这些天我使用代表:

  • 事件处理程序(用于GUI和更多)
  • 开始线程
  • callback(例如,用于asynchronousAPI)
  • LINQ和类似的(List.Find等)
  • 任何地方,我想有效地应用“模板”代码与一些专门的逻辑里面(代表提供专业化)

代表对于许多目的非常有用。

一个这样的目的是使用它们来过滤数据序列。 在这种情况下,您将使用一个谓词委托,它接受一个参数,并根据委托本身的实现返回true或false。

这是一个愚蠢的例子 – 我相信你可以外推一些更有用的东西:

using System; using System.Linq; using System.Collections.Generic; class Program { static void Main() { List<String> names = new List<String> { "Nicole Hare", "Michael Hare", "Joe Hare", "Sammy Hare", "George Washington", }; // Here I am passing "inMyFamily" to the "Where" extension method // on my List<String>. The C# compiler automatically creates // a delegate instance for me. IEnumerable<String> myFamily = names.Where(inMyFamily); foreach (String name in myFamily) Console.WriteLine(name); } static Boolean inMyFamily(String name) { return name.EndsWith("Hare"); } } 

发现另一个有趣的答案

一个同事问我这个问题 – .NET中的代表有什么意义? 我的回答非常短,而且他没有在网上find:延迟执行方法。

来源: LosTechies

就像LINQ正在做的一样。

您可以使用委托来声明函数型variables和参数。

考虑“资源借用”模式。 您想要控制资源的创build和清理,同时允许客户端代码“借用”其中的资源。

这声明了一个委托types。

 public delegate void DataReaderUser( System.Data.IDataReader dataReader ); 

任何匹配这个签名的方法都可以用来实例化这种types的委托。 在C#2.0中,这可以通过使用方法名称以及使用匿名方法来隐式完成。

此方法使用该types作为参数。 请注意委托的调用。

 public class DataProvider { protected string _connectionString; public DataProvider( string psConnectionString ) { _connectionString = psConnectionString; } public void UseReader( string psSELECT, DataReaderUser readerUser ) { using ( SqlConnection connection = new SqlConnection( _connectionString ) ) try { SqlCommand command = new SqlCommand( psSELECT, connection ); connection.Open(); SqlDataReader reader = command.ExecuteReader(); while ( reader.Read() ) readerUser( reader ); // the delegate is invoked } catch ( System.Exception ex ) { // handle exception throw ex; } } } 

该函数可以用下面的匿名方法调用。 请注意,匿名方法可以使用自身之外声明的variables。 这是非常方便的(虽然这个例子是有点人为的)。

 string sTableName = "test"; string sQuery = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='" + sTableName + "'"; DataProvider.UseReader( sQuery, delegate( System.Data.IDataReader reader ) { Console.WriteLine( sTableName + "." + reader[0] ); } ); 

代表经常可以用一种方法来代替接口,一个常见的例子就是观察者模式。 在其他语言中,如果您想要收到发生某种事情的通知,则可以定义如下所示的内容:

 class IObserver{ void Notify(...); } 

在C#中,这更常用表示事件,其中处理程序是一个委托,例如:

 myObject.SomeEvent += delegate{ Console.WriteLine("..."); }; 

如果必须将谓词传递给函数,例如从列表中select一组项目时,使用委托的另一个好处就是:

 myList.Where(i => i > 10); 

上面是一个lambda语法的例子,它也可以写成如下forms:

 myList.Where(delegate(int i){ return i > 10; }); 

另一个可以使用委托的地方是注册工厂function,例如:

 myFactory.RegisterFactory(Widgets.Foo, () => new FooWidget()); var widget = myFactory.BuildWidget(Widgets.Foo); 

我希望这有帮助!

我来这里真的很晚,但是我很难搞清楚代表们今天的目的,写了两个简单的程序,给出了相同的结果,我认为这个程序很好地解释了它们的目的。

NoDelegates.cs

 using System; public class Test { public const int MAX_VALUE = 255; public const int MIN_VALUE = 10; public static void checkInt(int a) { Console.Write("checkInt result of {0}: ", a); if (a < MAX_VALUE && a > MIN_VALUE) Console.WriteLine("max and min value is valid"); else Console.WriteLine("max and min value is not valid"); } public static void checkMax(int a) { Console.Write("checkMax result of {0}: ", a); if (a < MAX_VALUE) Console.WriteLine("max value is valid"); else Console.WriteLine("max value is not valid"); } public static void checkMin(int a) { Console.Write("checkMin result of {0}: ", a); if (a > MIN_VALUE) Console.WriteLine("min value is valid"); else Console.WriteLine("min value is not valid"); Console.WriteLine(""); } } public class Driver { public static void Main(string [] args) { Test.checkInt(1); Test.checkMax(1); Test.checkMin(1); Test.checkInt(10); Test.checkMax(10); Test.checkMin(10); Test.checkInt(20); Test.checkMax(20); Test.checkMin(20); Test.checkInt(30); Test.checkMax(30); Test.checkMin(30); Test.checkInt(254); Test.checkMax(254); Test.checkMin(254); Test.checkInt(255); Test.checkMax(255); Test.checkMin(255); Test.checkInt(256); Test.checkMax(256); Test.checkMin(256); } } 

Delegates.cs

 using System; public delegate void Valid(int a); public class Test { public const int MAX_VALUE = 255; public const int MIN_VALUE = 10; public static void checkInt(int a) { Console.Write("checkInt result of {0}: ", a); if (a < MAX_VALUE && a > MIN_VALUE) Console.WriteLine("max and min value is valid"); else Console.WriteLine("max and min value is not valid"); } public static void checkMax(int a) { Console.Write("checkMax result of {0}: ", a); if (a < MAX_VALUE) Console.WriteLine("max value is valid"); else Console.WriteLine("max value is not valid"); } public static void checkMin(int a) { Console.Write("checkMin result of {0}: ", a); if (a > MIN_VALUE) Console.WriteLine("min value is valid"); else Console.WriteLine("min value is not valid"); Console.WriteLine(""); } } public class Driver { public static void Main(string [] args) { Valid v1 = new Valid(Test.checkInt); v1 += new Valid(Test.checkMax); v1 += new Valid(Test.checkMin); v1(1); v1(10); v1(20); v1(30); v1(254); v1(255); v1(256); } } 

稍微不同的用途是加快思考; 即,而不是每次都使用reflection,您可以使用Delegate.CreateDelegate创build(types)委托给一个方法(一个MethodInfo ),并调用该委托。 每次通话都要快得多,因为支票已经完成了。

使用Expression ,您也可以在运行中创build代码,例如,您可以轻松地创build一个Expression ,该Expression代表在运行时select的types的+运算符(以提供运算符对generics的支持,语言不会提供); 你可以编译一个Expression到一个types化的委托 – 完成任务。

每次使用事件时都使用代表 – 这是他们工作的机制。

另外,代表对于使用LINQ查询等事情非常有用。 例如,许多LINQ查询都需要一个可以用于过滤的委托(通常是Func<T,TResult> )。

订阅事件处理程序

这里可能有一个例子。 您有一个方法来处理符合特定要求的对象。 但是,您希望能够以多种方式处理对象。 您不必创build单独的方法,只需将一个匹配的方法分配给委托,然后将委托传递给select对象的方法。 这样,您可以将不同的方法分配给一个select器方法。 我试图让这个容易理解。

我使用代表与线程进行通信。

例如,我可能有一个胜利forms的应用程序下载一个文件。 该应用程序启动一个工作线程来执行下载(这防止了GUI的locking)。 工作者线程使用委托将状态消息(例如下载进度)发送回主程序,以便GUI可以更新状态栏。

  1. 为事件处理程序

  2. 在方法参数中传递方法

第一行的用法是取代Observer / Observable(事件)模式。 第二,战略模式的一个不错的优雅版本。 可以收集各种其他用途,虽然比我认为的前两个更深奥。

事件,其他anynch操作

任何时候你想封装行为,但统一调用它。 事件处理程序,callback函数等。您可以使用接口和强制types来完成类似的事情,但有时,行为不一定与types对象绑定。 有时你只需要封装行为。

懒惰的参数初始化! 除了所有以前的答案(战略模式,观察者模式等),代表允许您处理参数的延迟初始化。 例如,假设你有一个函数Download(),需要花费很多时间并返回一个DownloadedObject。 该对象由存储根据特定条件使用。 通常情况下,您会:

 storage.Store(conditions, Download(item)) 

但是,对于委托(更确切地说,lambda),可以通过更改存储的签名来使其接收条件和Func <Item,DownloadedObject>,并像下面这样使用它:

 storage.Store(conditions, (item) => Download(item)) 

因此,存储将只在必要时评估委托,根据条件执行下载。

代表的使用

  1. 事件处理
  2. 多重铸造

In Array.Sort(T []数组,比较比较),List.Sort(比较比较)等比较参数

据我所知,委托可以转换为函数指针。 当与使用函数指针的本地代码进行交互操作时,这使得生活更加容易,因为它们可以有效地面向对象,即使原始程序员没有对此做出任何规定。

委托用于通过引用来调用方法。 例如:

  delegate void del_(int no1,int no2); class Math { public static void add(int x,int y) { Console.WriteLine(x+y); } public static void sub(int x,int y) { Console.WriteLine(xy); } } class Program { static void Main(string[] args) { del_ d1 = new del_(Math.add); d1(10, 20); del_ d2 = new del_(Math.sub); d2(20, 10); Console.ReadKey(); } }