你什么时候在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可以更新状态栏。
-
为事件处理程序
-
在方法参数中传递方法
第一行的用法是取代Observer / Observable(事件)模式。 第二,战略模式的一个不错的优雅版本。 可以收集各种其他用途,虽然比我认为的前两个更深奥。
事件,其他anynch操作
任何时候你想封装行为,但统一调用它。 事件处理程序,callback函数等。您可以使用接口和强制types来完成类似的事情,但有时,行为不一定与types或对象绑定。 有时你只需要封装行为。
懒惰的参数初始化! 除了所有以前的答案(战略模式,观察者模式等),代表允许您处理参数的延迟初始化。 例如,假设你有一个函数Download(),需要花费很多时间并返回一个DownloadedObject。 该对象由存储根据特定条件使用。 通常情况下,您会:
storage.Store(conditions, Download(item))
但是,对于委托(更确切地说,lambda),可以通过更改存储的签名来使其接收条件和Func <Item,DownloadedObject>,并像下面这样使用它:
storage.Store(conditions, (item) => Download(item))
因此,存储将只在必要时评估委托,根据条件执行下载。
代表的使用
- 事件处理
- 多重铸造
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(); } }