从我在谷歌上可以找到的,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仍然有非常常见的事件签名,而且对于我创建类的每一个特殊情况,它都是永远完成的. …
我试图理解为什么BeginInvoke方法不接受匿名方法.
void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (InvokeRequired)
{
//Won't compile
BeginInvoke(delegate(object sender, ProgressChangedEventArgs e)
{ bgWorker_ProgressChanged(sender, e); });
}
progressBar1.Increment(e.ProgressPercentage);
}
Run Code Online (Sandbox Code Playgroud)
它告诉我'无法从'匿名方法'转换为'System.Delegate',而当我将匿名方法转换为委托时,它确实有效吗?
BeginInvoke((progressDelegate)delegate { bgWorker_ProgressChanged(sender, e); });
Run Code Online (Sandbox Code Playgroud) 我是C#功能方面的新手,对不起,如果这个问题很蹩脚的话.
鉴于以下错误代码:
var jobSummaries = from job in jobs
where ...
select new
{
ID = job.ID,
Description = job.Description,
FileName = (job) => {
// primitive logic not
// worth to become a named method
try { return job.Files[0].LocalName); }
catch { return null as string; }
}
};
Run Code Online (Sandbox Code Playgroud)
此代码生成以下合理的编译器错误:
无法将lambda表达式赋给匿名类型属性
上面的代码将委托设置为FileName属性.但这不是我的目标.我希望代码像这样工作,但没有命名方法:
var jobSummaries = from job in jobs
where ...
select new
{
ID = job.ID,
Description = job.Description,
FileName = this.ExtractFileName(job)
};
...
private string ExtractFileName(Job job) …Run Code Online (Sandbox Code Playgroud) 可以在匿名c#方法中使用局部变量,即在以下代码中我只想执行一次计数.
IQueryable<Enquiry> linq = db.Enquiries;
if(...) linq = linq.Where(...);
if(...) linq = linq.Where(e =>
(x <= (from p in db.Orders where p.EnquiryId == e.Id select p).Count() &&
(from p in db.Orders where p.EnquiryId == e.Id select p).Count() <= y));
if(...) linq = linq.Where(...);
var result = (from e in linq select e);
Run Code Online (Sandbox Code Playgroud)
匿名函数是否有"让"?
更新:请注意,我在此语句后添加了几个Where子句,因此无法使用select关闭.
/尼尔斯
我想动态分配一个函数实现.
让我们从以下开始:
class Doer(object):
def __init__(self):
self.name = "Bob"
def doSomething(self):
print "%s got it done" % self.name
def doItBetter(self):
print "Done better"
Run Code Online (Sandbox Code Playgroud)
在其他语言中,我们将使doItBetter成为匿名函数并将其分配给对象.但是不支持Python中的匿名函数.相反,我们将尝试创建一个可调用的类实例,并将其分配给该类:
class Doer(object):
def __init__(self):
self.name = "Bob"
class DoItBetter(object):
def __call__(self):
print "%s got it done better" % self.name
Doer.doSomething = DoItBetter()
doer = Doer()
doer.doSomething()
Run Code Online (Sandbox Code Playgroud)
这给了我这个:
回溯(最近一次调用最后一次):第13行,在doer.doSomething()第9行,在调用 打印"%s让它做得更好"%self.name AttributeError:'DoItBetter'对象没有属性'name'
最后,我尝试将callable作为属性分配给对象实例并调用它:
class Doer(object):
def __init__(self):
self.name = "Bob"
class DoItBetter(object):
def __call__(self):
print "%s got it done better" % self.name
doer = Doer()
doer.doSomething = …Run Code Online (Sandbox Code Playgroud) 匿名方法本质上interface是一个Invoke方法:
type
TProc = reference to procedure;
IProc = interface
procedure Invoke;
end;
Run Code Online (Sandbox Code Playgroud)
现在,是否有可能将它们分配给实际的接口变量或将它们作为接口参数传递?
procedure TakeInterface(const Value: IInterface);
begin
end;
var
P: TProc;
I: IInterface;
begin
I := P; // E2010
TakeInterface(P); // E2010
end;
Run Code Online (Sandbox Code Playgroud)
[DCC32错误] E2010不兼容的类型:'IInterface'和'过程,无类型指针或无类型参数'
有很多对象,不能通过接口引用保持活着.因此,它们被包裹在一个封闭物中并被它摧毁,"智能指针":
type
I<T> = reference to function : T;
TInterfaced<T: class> = class (TInterfacedObject, I<T>)
strict private
FValue: T;
function Invoke: T; // Result := FValue;
public
constructor Create(const Value: T); // FValue := Value;
destructor …Run Code Online (Sandbox Code Playgroud) 随着lambda表达式(内联代码)等新功能的出现,它是否意味着我们不再需要使用委托或匿名方法了?在我看过的几乎所有样本中,都是使用新语法进行重写.
我们仍然需要使用delegates和lambda表达式的任何地方都不起作用?
为什么C#7编译器将本地函数转换为其父函数所在的同一类中的方法.对于匿名方法(和Lambda表达式),编译器为每个父函数生成一个嵌套类,它将包含所有的匿名方法作为实例方法?
例如,C#代码(匿名方法):
internal class AnonymousMethod_Example
{
public void MyFunc(string[] args)
{
var x = 5;
Action act = delegate ()
{
Console.WriteLine(x);
};
act();
}
}
Run Code Online (Sandbox Code Playgroud)
将生成IL代码(匿名方法)类似于:
.class private auto ansi beforefieldinit AnonymousMethod_Example
{
.class nested private auto ansi sealed beforefieldinit '<>c__DisplayClass0_0'
{
.field public int32 x
.method assembly hidebysig instance void '<MyFunc>b__0' () cil managed
{
...
AnonymousMethod_Example/'<>c__DisplayClass0_0'::x
call void [mscorlib]System.Console::WriteLine(int32)
...
}
...
}
...
Run Code Online (Sandbox Code Playgroud)
虽然这样,C#代码(Local Function):
internal class LocalFunction_Example
{
public …Run Code Online (Sandbox Code Playgroud)