Is this C# 'closure' still valid across a parameter reference? -
let's take simple case .net smtpclient, can following (ignoring credentials, ssl , exception handling):
async task sendmail() { var m = new mailmessage(...); var s = new smtpclient(host, port); s.sendcompleted += (s, e) => { m.dispose(); s.dispose(); }; await s.sendmailasync(m); }
all fine; func dispose()ing called whenever async sending finishes. m , s within containing scope declared, no problem there.
but had following:
smtpclient setupmailclient(mailmessage mail) { var smtpclient = new smtpclient(host, port); smtpclient.sendcompleted += (s, e) => { mail.dispose(); smtpclient.dispose(); }; return smtpclient; } async task sendmail() { var m = new mailmessage(...); var s = setupmailclient(m); await s.sendmailasync(m); }
now, calling await sendmail() still safe? closure still valid? pass in reference mailmessage 'mail' - copy of reference, valid in context of setupmailclient(). overthinking it, or still safe usage?
both programs behave identically. second program more confusing follow, in sendmail
method creating mailmessage
, 1 responsible disposing of (by convention). doesn't dispose of object , method calls confuse others reading code. should have sendmail
dispose of mailmessage
in case (which can trivially done wrapping in using
.
we pass in reference mailmessage 'mail' - copy of reference, valid in context of setupmailclient().
it's not valid in context of setupmailclient
. it's valid reference entire lifetime of object. it's in scope in context of setupmailclient
, meaning code within method allowed refer parameter name. scope , lifetime different concepts. scope of mail
method, lifetime of variable can (and in case is) longer until method returns (due closure).
Comments
Post a Comment