{"id":6143,"date":"2007-05-03T19:22:00","date_gmt":"2007-05-03T19:22:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/vbteam\/2007\/05\/03\/closures-in-vb-part-2-method-calls\/"},"modified":"2024-07-05T14:46:57","modified_gmt":"2024-07-05T21:46:57","slug":"closures-in-vb-part-2-method-calls","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/vbteam\/closures-in-vb-part-2-method-calls\/","title":{"rendered":"Closures in VB Part 2: Method Calls"},"content":{"rendered":"<p>For previous articles in this series, please see<\/p>\n<ul>\n<li><a href=\"http:\/\/blogs.msdn.com\/vbteam\/archive\/2007\/05\/02\/closures-in-vb-part-1.aspx\">Part 1 &#8211; The basics<\/a><\/li>\n<\/ul>\n<p>Jared here again.&nbsp; This part of the series will focus on how method calls are handled in closures.&nbsp;&nbsp;As stated in the previous article, the purpose of closures is to allow all operations inside a lambda or query expression that would normally be available inside the function or sub.&nbsp; To do this closures often need to capture (or lift) relevant variables from the function into the generated class.<\/p>\n<p>There are&nbsp;2 types of methods and method calls that closures have to handle.&nbsp; <\/p>\n<ol>\n<li>Method calls to a shared method or methods on modules.\n<li>Method calls to instance members of a class <\/li>\n<\/ol>\n<p><strong>Scenario #1 <\/strong><\/p>\n<p>Below is an example of a method call inside a lambda expression for scenario #1.&nbsp; <\/p>\n<pre><span>Module<\/span> M1\n    <span>Function<\/span> MyValue() <span>As<\/span> <span>Integer<\/span>\n        <span>Return<\/span> <span>42<\/span>\n    <span>End<\/span> <span>Function<\/span>\n    <span>Sub<\/span> Example1()\n        <span>Dim<\/span> x = <span>5<\/span>\n        <span>Dim<\/span> f = <span>Function<\/span>() x + MyValue()\n    <span>End<\/span> <span>Sub<\/span>\n<span>End<\/span> <span>Module<\/span><\/pre>\n<p>Here we are calling a&nbsp;module method inside a lambda.&nbsp; Module Methods or Shared methods can be called from anywhere because they require no specific variable for the call.&nbsp; This requires no special work from closures as the call can just be made naturally.<\/p>\n<pre>    <span>Class<\/span> Closure\n        <span>Private<\/span> x <span>As<\/span> <span>Integer<\/span>\n        <span>Function<\/span> Lambda_f() <span>As<\/span> <span>Integer<\/span>\n            <span>Return<\/span> x + M1.MyValue\n        <span>End<\/span> <span>Function<\/span>\n    <span>End<\/span> <span>Class<\/span>\n<\/pre>\n<p><strong>Scenario #2<\/strong><\/p>\n<p>Calling an instance method is more difficult than a shared method because it requires the referenc &#8220;Me&#8221;.&nbsp; If you don&#8217;t type this specifically in code the VB Compiler will add it for you under the hood.&nbsp; To make this work the closures code will also &#8220;lift&#8221; the variable &#8220;Me&#8221; in the same way that it lifts normal variables in a function.&nbsp; <\/p>\n<p>Calling a instance method inside a lambda expression is little difference than calling a member method on a variable used in a lambda.&nbsp; The only difference is the variable is &#8220;Me&#8221;.&nbsp; For example<\/p>\n<pre><span>Class<\/span> C1\n    <span>Private<\/span> m_myValue <span>As<\/span> <span>Integer<\/span>\n    <span>Function<\/span> MyValue() <span>As<\/span> <span>Integer<\/span>\n        <span>Return<\/span> m_myValue\n    <span>End<\/span> <span>Function<\/span>\n    <span>Sub<\/span> Example2()\n        <span>Dim<\/span> x = <span>5<\/span>\n        <span>Dim<\/span> f = <span>Function<\/span>() x + MyValue()\n    <span>End<\/span> <span>Sub<\/span>\n<span>End<\/span> <span>Class<\/span><\/pre>\n<p>In this case we need to access both &#8220;x&#8221; and &#8220;Me.MyValue()&#8221; from the closure.&nbsp; The generated code will create space for both of these variables and the transformed code in Example2 will store both of the values.<\/p>\n<pre><span>Class<\/span> Closure\n    <span>Private<\/span> x <span>As<\/span> <span>Integer<\/span>\n    <span>Private<\/span> OriginalMe <span>As<\/span> C1\n    <span>Function<\/span> Lambda_f()\n        <span>Return<\/span> x + OriginalMe.MyValue()\n    <span>End<\/span> <span>Function<\/span>\n<span>End<\/span> <span>Class<\/span><\/pre>\n<pre>    <span>Sub<\/span> Example2()\n        <span>Dim<\/span> c <span>As<\/span> <span>New<\/span> Closure\n        c.x = <span>5<\/span>\n        c.OriginalMe = <span>Me<\/span>\n        <span>Dim<\/span> f = <span>New<\/span> Func(Of <span>Integer<\/span>)(<span>AddressOf<\/span> c.Lambda_f)\n    <span>End<\/span> <span>Sub<\/span><\/pre>\n<p>As usual, the generated code is much uglier but this essentially what will be generated.&nbsp; That wraps it up for method calls.&nbsp; In the next part, I will discuss the variable liftetime and scoping issues that come into play with closures.&nbsp; <\/p>\n<p>Jared Parsons<\/p>\n<p><a href=\"http:\/\/blogs.msdn.com\/jaredpar\">http:\/\/blogs.msdn.com\/jaredpar<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>For previous articles in this series, please see Part 1 &#8211; The basics Jared here again.&nbsp; This part of the series will focus on how method calls are handled in closures.&nbsp;&nbsp;As stated in the previous article, the purpose of closures is to allow all operations inside a lambda or query expression that would normally be [&hellip;]<\/p>\n","protected":false},"author":260,"featured_media":8818,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[192,195],"tags":[78,94,117],"class_list":["post-6143","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-featured","category-visual-basic","tag-jared-parsons","tag-linqvb9","tag-orcas"],"acf":[],"blog_post_summary":"<p>For previous articles in this series, please see Part 1 &#8211; The basics Jared here again.&nbsp; This part of the series will focus on how method calls are handled in closures.&nbsp;&nbsp;As stated in the previous article, the purpose of closures is to allow all operations inside a lambda or query expression that would normally be [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts\/6143","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/users\/260"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/comments?post=6143"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts\/6143\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/media\/8818"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/media?parent=6143"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/categories?post=6143"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/tags?post=6143"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}