说如果我听一个事件:
Subject.NewEvent += delegate(object sender, NewEventArgs e)
{
//some code
});
Run Code Online (Sandbox Code Playgroud)
现在我如何取消注册此活动?或者只是让内存泄漏?
我不能成为唯一一个厌倦了定义和命名委托只需要一个需要委托的东西的人.例如,我想从可能的其他线程调用表单中的.Refresh(),所以我编写了这段代码:
private void RefreshForm()
{
if (InvokeRequired)
Invoke(new InvokeDelegate(Refresh));
else
Refresh();
}
Run Code Online (Sandbox Code Playgroud)
我甚至不确定我必须这样做,我只是读得足以害怕它在以后的某个阶段不起作用.
InvokeDelegate实际上是在另一个文件中声明的,但是我真的需要一个专门用于此的整个委托吗?根本没有任何通用代表?
我的意思是,例如,有一个Pen类,但也有Pens.选择笔,所以你不必重拍整个事情.它不一样,但我希望你理解我的意思.
基本上我有一个匿名的方法,我用于我的BackgroundWorker:
worker.DoWork += ( sender, e ) =>
{
foreach ( var effect in GlobalGraph.Effects )
{
// Returns EffectResult
yield return image.Apply (effect);
}
};
Run Code Online (Sandbox Code Playgroud)
当我这样做时,编译器告诉我:
"yield语句不能在匿名方法或lambda表达式中使用"
那么在这种情况下,最优雅的方法是什么?顺便说一句,这个DoWork方法在静态方法中,以防对解决方案很重要.
请参阅以下代码:
public abstract class Base
{
public virtual void Foo<T>() where T : class
{
Console.WriteLine("base");
}
}
public class Derived : Base
{
public override void Foo<T>()
{
Console.WriteLine("derived");
}
public void Bang()
{
Action bang = new Action(delegate { base.Foo<string>(); });
bang(); //VerificationException is thrown
}
}
Run Code Online (Sandbox Code Playgroud)
new Derived().Bang();抛出一个例外.在Bang我生成的方法生成的CIL里面:
call instance void ConsoleApp.Derived::'<>n__FabricatedMethod1'<string>()
Run Code Online (Sandbox Code Playgroud)
和编译器生成方法的签名:
method private hidebysig
instance void '<>n__FabricatedMethod1'<T> () cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
) …Run Code Online (Sandbox Code Playgroud) 德尔福2009,在一些很酷的东西,也刚刚得到匿名方法.我已经看过这些示例,以及关于匿名方法的博客文章,但我还没有得到它们.有人可以解释为什么我应该兴奋吗?
我将使用匿名方法创建BackgroundWorker.
我写了以下代码:
BackgroundWorker bgw = new BackgroundWorker();
bgw.DoWork += new DoWorkEventHandler(
() =>
{
int i = 0;
foreach (var item in query2)
{
....
....
}
}
);
Run Code Online (Sandbox Code Playgroud)
但是委托'System.ComponentModel.DoWorkEventHandler'不接受'0'参数,我必须将两个对象传递给匿名方法:object sender,DoWorkEventArgs e
你能指导我,我怎么做?谢谢.
我希望我能恰当地提出问题的标题.
在c#中,我可以使用lambdas(作为委托),或者使用较旧的委托语法来执行此操作:
Func<string> fnHello = () => "hello";
Console.WriteLine(fnHello());
Func<string> fnHello2 = delegate()
{
return "hello 2";
};
Console.WriteLine(fnHello2());
Run Code Online (Sandbox Code Playgroud)
那么为什么我不能"内联"lambda或委托体,并避免在命名变量中捕获它(使其匿名)?
// Inline anonymous lambda not allowed
Console.WriteLine(
(() => "hello inline lambda")()
);
// Inline anonymous delegate not allowed
Console.WriteLine(
(delegate() { return "hello inline delegate"; })()
);
Run Code Online (Sandbox Code Playgroud)
在javascript中工作的示例(仅用于比较)是:
alert(
(function(){ return "hello inline anonymous function from javascript"; })()
);
Run Code Online (Sandbox Code Playgroud)
这会产生预期的警报框.
更新:看起来你可以在C#中使用内联匿名lambda,如果你适当地进行转换,但是()的数量开始让它变得难以驾驭.
// Inline anonymous lambda with appropriate cast IS allowed
Console.WriteLine(
((Func<string>)(() => "hello inline anonymous …Run Code Online (Sandbox Code Playgroud) 将两个参数传递给线程池上的新线程有时会很复杂,但看起来使用lambda表达式和匿名方法,我可以这样做:
public class TestClass
{
public void DoWork(string s1, string s2)
{
Console.WriteLine(s1);
Console.WriteLine(s2);
}
}
try
{
TestClass test = new TestClass();
string s1 = "Hello";
string s2 = "World";
ThreadPool.QueueUserWorkItem(
o => test.DoWork(s1, s2)
);
}
catch (Exception ex)
{
//exception logic
}
Run Code Online (Sandbox Code Playgroud)
现在,我肯定简化了这个例子,但这些要点是关键:
这有什么问题吗?
另一种方法是创建一个实现具有3个成员的不可变类型的新类:test,s1和s2.这似乎是额外的工作,在这一点上没有任何好处.
我想知道有什么区别.目前我正在学习这些东西,在我看来,这些都是一样的:
delegate void X();
X instanceOfX;
instanceOfX = delegate() { code };
instanceOfX = () => { code };
Run Code Online (Sandbox Code Playgroud)
另外如果lambda更新,我应该只使用lambda并忘记匿名方法吗?
我对Delphi代码有一些意外的访问冲突,我认为是正确的,但似乎是错误编译的.我可以减少它
procedure Run(Proc: TProc);
begin
Proc;
end;
procedure Test;
begin
Run(
procedure
var
S: PChar;
procedure Nested;
begin
Run(
procedure
begin
end);
S := 'Hello, world!';
end;
begin
Run(
procedure
begin
S := 'Hello';
end);
Nested;
ShowMessage(S);
end);
end;
Run Code Online (Sandbox Code Playgroud)
对我来说发生的S := 'Hello, world!'是存储在错误的位置.因此,会引发访问冲突,或者ShowMessage(S)显示"Hello"(有时,在释放用于实现匿名过程的对象时会引发访问冲突).
我正在使用Delphi XE,安装了所有更新.
我怎么知道这会导致问题?我知道如何重写我的代码以避免匿名程序,但我很难弄清楚它们在哪些情况下会导致错误的代码,所以我不知道在哪里避免它们.
我很有兴趣知道这是否在Delphi的更高版本中得到修复,但仅仅是有趣的,此时升级不是一个选项.
在QC上,最新的报告我可以找到类似的#91876,但这在Delphi XE中得到了解决.
更新:
基于AlexSC的评论,稍作修改:
...
procedure Nested;
begin
Run(
procedure
begin
S := S;
end);
S := 'Hello, world!';
end;
...
Run Code Online (Sandbox Code Playgroud)
确实有效.
生成的机器代码
S := 'Hello, …Run Code Online (Sandbox Code Playgroud)