你在C#中对代表的用法是什么?
既然我们在C#中有lambda表达式和匿名方法,我就更多地使用委托了.在C#1中,你总是需要一个单独的方法来实现逻辑,使用委托通常没有意义.这些天我使用代表:
事件处理程序(用于GUI等)
启动线程
回调(例如异步API)
LINQ和类似的(List.Find等)
我希望在其他地方有效地应用"模板"代码,其中包含一些专门的逻辑(代表提供专业化)
代表们在很多方面非常有用.
一个这样的目的是使用它们来过滤数据序列.在这种情况下,您将使用谓词委托,该委托接受一个参数并根据委托本身的实现返回true或false.
这是一个愚蠢的例子 - 我相信你可以推断一些更有用的东西:
using System; using System.Linq; using System.Collections.Generic; class Program { static void Main() { Listnames = new List { "Nicole Hare", "Michael Hare", "Joe Hare", "Sammy Hare", "George Washington", }; // Here I am passing "inMyFamily" to the "Where" extension method // on my List . The C# compiler automatically creates // a delegate instance for me. IEnumerable myFamily = names.Where(inMyFamily); foreach (String name in myFamily) Console.WriteLine(name); } static Boolean inMyFamily(String name) { return name.EndsWith("Hare"); } }
找到另一个有趣的答案
一位同事刚刚问我这个问题 - .NET代表的观点是什么?我的答案很短,而且他没有在网上找到的答案:推迟执行方法.
资料来源:LosTechies
就像LINQ一样.
您可以使用委托来声明函数类型的变量和参数.
例
考虑"资源借用"模式.您希望控制资源的创建和清理,同时允许客户端代码在其间"借用"资源.
这声明了一个委托类型.
public delegate void DataReaderUser( System.Data.IDataReader dataReader );
匹配此签名的任何方法都可用于实例化此类型的委托.在C#2.0中,这可以通过使用方法的名称以及使用匿名方法隐式完成.
此方法使用类型作为参数.请注意委托的调用.
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; } } }
可以使用匿名方法调用该函数,如下所示.请注意,匿名方法可以使用在其自身之外声明的变量.这非常方便(虽然这个例子有点人为).
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("..."); };
如果必须将谓词传递给函数,例如从列表中选择一组项时,另一个使用委托的好地方:
myList.Where(i => i > 10);
上面是lambda语法的一个例子,它也可以写成如下:
myList.Where(delegate(int i){ return i > 10; });
使用委托可能有用的另一个地方是注册工厂功能,例如:
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); } }
稍微不同的用途是加速反射; 即,不是每次都使用反射,您可以使用Delegate.CreateDelegate
创建方法(a MethodInfo
)的(类型)委托,并调用该委托.然后,每次调用都会更快,因为检查已经完成.
有了Expression
,您也可以动态创建代码 - 例如,您可以轻松地创建一个Expression
代表运算符选择的类型的+运算符(为泛型提供操作员支持,语言不提供) ; 你可以编译Expression
一个类型的委托 - 完成工作.
任何时候使用事件都会使用代理 - 这是它们工作的机制.
此外,委托对于使用LINQ查询等内容非常有用.例如,许多LINQ查询采用Func
可以用于过滤的委托(通常).