我实例化了一个匿名类的对象,我添加了一个新方法.
Date date = new Date() {
public void someMethod() {}
}
Run Code Online (Sandbox Code Playgroud)
我想知道是否有可能从外部调用此方法,类似于:
date.someMethod();
Run Code Online (Sandbox Code Playgroud) 这是一个构造的例子.我不想在这里发布原始代码.我尝试提取相关部分.
我有一个管理监听器列表的界面.
TListenerProc = reference to procedure (SomeInt : ISomeInterface);
ISomeInterface = interface
procedure AddListener (Proc : TListenerProc);
end;
Run Code Online (Sandbox Code Playgroud)
现在我注册一个监听器:
SomeObj.AddListener (MyListener);
procedure MyListener (SomeInt : ISomeInterface);
begin
ExecuteSynchronized (procedure
begin
DoSomething (SomeInt);
end);
end;
Run Code Online (Sandbox Code Playgroud)
我确实得到了内存泄漏.永远不会释放匿名方法和接口.我怀疑这是由于某种循环引用.匿名方法保持界面生效,界面保持匿名方法生效.
两个问题:
提前致谢!
编辑:在一个小到足以在此发布的应用程序中重现这一点并不容易.我现在能做的最好的事情如下.匿名方法不会在这里发布:
program TestMemLeak;
{$APPTYPE CONSOLE}
uses
Generics.Collections, SysUtils;
type
ISomeInterface = interface;
TListenerProc = reference to procedure (SomeInt : ISomeInterface);
ISomeInterface = interface
['{DB5A336B-3F79-4059-8933-27699203D1B6}']
procedure AddListener (Proc : TListenerProc);
procedure NotifyListeners;
procedure Test;
end;
TSomeInterface = class (TInterfacedObject, ISomeInterface) …Run Code Online (Sandbox Code Playgroud) delphi memory-management interface anonymous-methods delphi-2010
我正在读这个被问到的问题:避免回调中的内存泄漏?
我很困惑,直到有人回答以下问题:
"这种方法的问题是你不能有一个只在集合中引用的监听器,因为它会随机消失(在下一个GC上)"
我是否理解使用弱引用(如存储在WeakHashMap中)与匿名侦听器不兼容?
我通常传递这样的听众:
public static void main(String[] args) {
final Observable obs = new SomeObservable();
obs.addObserver(new Observer() {
public void update(final Observable o, final Object arg) {
System.out.println("Notified");
}
});
obs.notifyObservers();
... // program continues its life here
}
private static final class SomeObservable extends Observable {
@Override
public void addObserver(final Observer o) {
super.addObserver(o);
setChanged(); // shouldn't be done from here (unrelated to the question)
}
}
Run Code Online (Sandbox Code Playgroud)
我使用CopyOnWriteArrayList跟踪侦听器(上面的默认Observable显然使用了一个旧的Vector,但它只是一个示例来说明我通常如何创建一个匿名类来用作侦听器). …
任何人都可以提供匿名方法和lambda表达式之间的简洁区别吗?
使用匿名方法:
private void DoSomeWork()
{
if (textBox1.InvokeRequired)
{
//textBox1.Invoke((Action)(() => textBox1.Text = "test"));
textBox1.Invoke((Action)delegate { textBox1.Text = "test"; });
}
}
Run Code Online (Sandbox Code Playgroud)
是仅仅将普通的lambda表达式强制转换为强类型的委托,还是有更多的表达式.
我很清楚一个强类型的代表就像跟随
UpdateTextDelegate mydelegate = new UpdateTextDelegate(MethodName)
Run Code Online (Sandbox Code Playgroud)
足够作为类型的参数System.Delegate,但匿名方法的想法对我来说是新的.
我正在尝试制作事件处理程序列表,其中handler是方法引用.要删除特定的处理程序,我需要在列表中找到它.但是我如何比较两个方法引用的代码地址?
type
TEventHandler = reference to procedure;
procedure TestProc;
begin
end;
procedure TForm26.FormCreate(Sender: TObject);
var
Handlers: TList<TEventHandler>;
begin
Handlers := TList<TEventHandler>.create;
try
Handlers.Add(TestProc);
Handlers.Remove(TestProc); { doesn't work }
Assert(Handlers.Count=0); { fails }
Assert(Handlers.IndexOf(TestProc)>=0); { fails }
finally
FreeAndNil(Handlers);
end;
end;
Run Code Online (Sandbox Code Playgroud)
TList <>的默认比较器不能正确比较方法引用.我该如何比较它们?是否存在类似于TMethod的结构,但是方法参考?
StackOverflow上的几个C#问题询问如何使用out或ref参数创建匿名委托/ lambdas .例如,见:
为此,您只需指定参数的类型,如:
public void delegate D(out T p);
// ...
D a = (out T t) => { ... }; // Lambda syntax.
D b = delegate(out T t) { ... }; // Anonymous delegate syntax.
Run Code Online (Sandbox Code Playgroud)
我很好奇的是为什么明确要求类型.有这种情况的特殊原因吗?也就是说,从编译器/语言的角度来看,为什么不允许以下内容?
D a = (out t) => { ... }; // Lambda syntax -- implicit typing.
D b = delegate(out t) { ... }; // Anonymous delegate syntax -- implicit typing.
Run Code Online (Sandbox Code Playgroud)
甚至更好,只是:
D a = (t) …Run Code Online (Sandbox Code Playgroud) 函数返回匿名函数.我想将结果分配给变量.但是编译器认为我正在尝试分配函数而不是函数的结果.我该如何解决这个问题?
program Project9;
{$APPTYPE CONSOLE}
type
TMyEvent = reference to function: string;
var
v1: TMyEvent;
function GetHandler: TMyEvent;
begin
Result := function: string
begin
Result := '';
end;
end;
begin
v1 := GetHandler; // <- Incompatible types: 'TMyEvent' and 'Procedure'
end.
Run Code Online (Sandbox Code Playgroud)
注意:我确实有一个解决方法,但我希望在不引入包装器的情况下解决这个问题:
program Project9;
{$APPTYPE CONSOLE}
type
TMyEvent = reference to function: string;
TWrapper = record
FHandler: TMyEvent;
end;
var
v1: TMyEvent;
function GetHandler: TWrapper;
begin
Result.FHandler := function: string
begin
Result := '';
end;
end;
begin
v1 := GetHandler.FHandler; …Run Code Online (Sandbox Code Playgroud) delphi variables function-pointers function anonymous-methods
所以,每次我在一个方法中编写一个lambda表达式或匿名方法时,我都没有完全正确,我被迫重新编译并重新启动整个应用程序或单元测试框架以便修复它.这非常令人烦恼,我最终浪费的时间比我首先使用这些结构所节省的时间多.如果可以的话,我会尽量远离他们,尽管Linq和lambdas是我最喜欢的C#功能之一.
我想有一个很好的技术理由说明为什么会这样,也许有人知道呢?此外,有谁知道它是否会在VS2010中修复?
谢谢.
从我在谷歌上可以找到的,VB.NET只有一个语句lambdas,而不是多语句匿名函数.但是,我读到的所有文章都在谈论旧版本的VB.NET,我找不到比vs2008 beta 1或2更新的内容.
所以问题是:如何在VB.NET中执行此操作?
C#代码:
private void HandleErrors( Action codeBlock ){
try{
codeBlock();
}catch(Exception e){
//log exception, etc
}
}
HandleErrors(() => {
var x = foo();
x.DoStuff();
etc
});
Run Code Online (Sandbox Code Playgroud) 由于在Delphi中出现了匿名方法,我想在VCL组件事件中使用它们.显然,为了向后兼容,VCL没有更新,所以我设法做了一个简单的实现,但有几点需要注意.
type
TNotifyEventDispatcher = class(TComponent)
protected
FClosure: TProc<TObject>;
procedure OnNotifyEvent(Sender: TObject);
public
class function Create(Owner: TComponent; Closure: TProc<TObject>): TNotifyEvent; overload;
function Attach(Closure: TProc<TObject>): TNotifyEvent;
end;
implementation
class function TNotifyEventDispatcher.Create(Owner: TComponent; Closure: TProc<TObject>): TNotifyEvent;
begin
Result := TNotifyEventDispatcher.Create(Owner).Attach(Closure)
end;
function TNotifyEventDispatcher.Attach(Closure: TProc<TObject>): TNotifyEvent;
begin
FClosure := Closure;
Result := Self.OnNotifyEvent
end;
procedure TNotifyEventDispatcher.OnNotifyEvent(Sender: TObject);
begin
if Assigned(FClosure) then
FClosure(Sender)
end;
end.
Run Code Online (Sandbox Code Playgroud)
以下是它的用法:
procedure TForm1.FormCreate(Sender: TObject);
begin
Button1.OnClick := TNotifyEventDispatcher.Create(Self,
procedure (Sender: TObject)
begin
Self.Caption := 'DONE!'
end)
end;
Run Code Online (Sandbox Code Playgroud)
我相信很简单,有两个缺点:
我必须创建一个组件来管理匿名方法的生命周期(我浪费了更多的内存,对于间接方式来说它有点慢,我仍然希望在我的应用程序中更清晰的代码)
我必须为每个事件签名实现一个新类(非常简单).这个有点复杂,VCL仍然有非常常见的事件签名,而且对于我创建类的每一个特殊情况,它都是永远完成的. …