为什么lambda表达式没有“实习”?字符串是引用类型,但它们是不可变的。这允许它们由编译器实现;出现相同字符串文字的地方,可以引用相同的对象。委托也是不可变的引用类型。(使用+=运算符向多播委托添加方法构成赋值;这不是可变性。)而且,就像字符串一样,有一种“文字”方式来表示代码中的委托,使用lambda表达式,例如:Funcfunc=()=>5;语句右侧是一个Func类型的表达式;但我没有在任何地方显式调用Func构造函数(也没有发生隐式转换)。所以我认为它基本上是一个字面意思。我在这里误解了我对“文字”的定义吗?无论如何,这是我的问题。如果我有两个变量,比如Func类型,我将两个相同的lambda表达式分配给:Funcx=()=>5;功能=()=>5;...是什么阻止编译器将它们视为同一个Func对象?我问是因为C#4.0语言规范的第6.5.1节明确指出:允许(但不是必需)返回相同的委托实例。此处使用术语语义相同的意思是在所有情况下,匿名函数的执行将在给定相同参数的情况下具有相同的效果。当我读到它时,这让我感到惊讶;如果明确允许这种行为,我希望它能起作用。但事实似乎并非如此。事实上,这给许多开发人员带来了麻烦,尤其是当使用lambda表达式成功附加事件处理程序而无法删除它们时。例如:classEventSender{publiceventEventHandlerEvent;publicvoidSend(){EventHandlerhandler=this.Event;if(handler!=null){handler(this,EventArgs.Empty);}}}classProgram{staticstring_message="Hello,world!";staticvoidMain(){varsender=newEventSender();sender.Event+=(obj,args)=>Console.WriteLine(_message);发件人。发送();//除非我弄错了,否则这个lambda表达式在语义上与上面的//相同。但是,处理程序没有被删除,这表明//构造了一个不同的委托实例。sender.Event-=(obj,args)=>控制台。写行(_消息);//这会打印“Hello,world!”again.sender.Send();有没有理由不实现这种行为——与委托实例相同的匿名方法的语义?你把它称为字面意思是错误的,IMO。它只是一个可转换为委托类型的表达式。现在关于“实习”部分——缓存了一些lambda表达式,因为对于单个lambda表达式,有时可以创建单个实例并重用,但经常会遇到那行代码。有些不是这样处理的:它通常取决于lambda表达式是否捕获任何非静态变量(无论是通过“this”还是本机方法)。这是此缓存的示例:usingSystem;classProgram{staticvoidMain(){Actionfirst=GetFirstAction();首先-=GetFirstAction();Console.WriteLine(first==null);//打印TrueActionsecond=GetSecondAction();第二-=GetSecondAction();Console.WriteLine(second==null);//打印False}staticActionGetFirstAction(){return()=>Console.WriteLine("First");}staticActionGetSecondAction(){inti=0;return()=>Console.WriteLine("第二个"+i);在这种情况下,我们可以看到第一个操作被缓存了(或者至少有两个equal,事实上Reflector表明它确实被缓存在一个静态字段中)。第二个动作为对GetSecondAction的两次调用创建了两个不相等的Action实例,这就是为什么“second”最后不为空的原因。实习出现在代码中不同位置但具有相同源代码的lambda是另一回事。我怀疑这样做非常复杂(毕竟,相同的源代码在不同的地方可能意味着不同的东西),我当然不想依赖它。如果它不值得依赖,并且为编译器团队做了很多工作,我认为这不是打发他们时间的最佳方式。这种行为——具有相同语义的匿名方法的委托实例——没有实现的原因是什么?是的。因为花在棘手的优化上的时间几乎对任何人都没有好处,所以花时间设计、实施、测试和维护对人们有益的功能。其他答案带来好处。我真的没有任何技术-每个函数都从-100点开始。通常,引用同一String实例的String变量与引用包含相同字符序列的不同String的两个变量之间没有区别。代表也是如此。假设我有两个代表,分配给两个不同的lambda表达式。然后我将两个代表订阅到一个事件处理程序,并取消订阅一个。结果应该是什么?如果在vb或C#中有一种方法可以指定不引用Me/this的匿名方法或lambda应被视为静态方法,那么生成一个可以在其整个生命周期中重复使用的委托将很有用。应用。但是,没有语法表明这一点,并且编译器决定使用不同的lambda表达式返回同一实例将是一个潜在的破坏性更改。编辑我猜规范允许它,即使如果任何代码依赖于不同的实例,它可能是一个潜在的破坏性变化。这是允许的,因为C#团队无法控制它。它们严重依赖委托(CLR+BCL)的实现细节和JIT编译器的优化器。现在CLR和抖动实现已经激增,没有理由认为它会结束。关于委托规则,CLI规范非常清晰,不足以确保所有这些不同的团队最终会实现一个保证委托对象相等性一致的实现。至少因为它阻碍了未来的创新。这里有很多优化。Lambda不能,因为它们使用对象来包含捕获的局部变量。每次构造委托时,此实例都不同。以上就是C#学习教程:lambda表达式为什么没有“实践”?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
