{"id":108775,"date":"2023-09-15T07:00:00","date_gmt":"2023-09-15T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=108775"},"modified":"2023-09-16T07:10:58","modified_gmt":"2023-09-16T14:10:58","slug":"20230915-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20230915-00\/?p=108775","title":{"rendered":"How can I prevent myself from using a parameter after I&#8217;ve extracted all value from it?"},"content":{"rendered":"<p>Suppose you have a function that takes a parameter that you want to transform in some way, and you want to require that all future access to the parameter be done through the transformed version. One example is a wrapper class that does logging.\u00b9<\/p>\n<pre>struct WidgetRefWrapper\r\n{\r\n    WidgetRefWrapper(\r\n        Widget&amp; widget,\r\n        Logger&amp; logger) :\r\n    m_widget(widget), m_logger(logger) {}\r\n    \r\n    void Toggle() try\r\n    {\r\n        m_logger.Log(\"Toggling the widget\");\r\n        m_widget.Toggle();\r\n        m_logger.Log(\"Toggled the widget\");\r\n    } catch (...) {\r\n        m_logger.Log(\"Exception while toggling the widget\");\r\n        throw;\r\n    }\r\n\r\nprivate:\r\n    Widget&amp; m_widget;\r\n    Logger&amp; m_logger;\r\n};\r\n\r\nvoid DoSomething(Widget&amp; widget)\r\n{\r\n    Logger&amp; logger = GetCurrentLogger();\r\n    WidgetWrapper wrapper(widget, logger);\r\n\r\n    \/\/ Do not use the widget directly!\r\n    \/\/ Always use the wrapper!\r\n\r\n    if (needs_toggling) {\r\n        wrapper.Toggle();\r\n    }\r\n}\r\n<\/pre>\n<p>You want that &#8220;Do not use the widget directly!&#8221; comment to have some teeth. Can you &#8220;poison&#8221; the <code>widget<\/code> parameter so it cannot be used any more?<\/p>\n<p>One idea is to split the method into two. The outer function does the preliminary wrapping, and the worker function does the bulk of the work.<\/p>\n<pre>void DoSomething(Widget&amp; widget)\r\n{\r\n    Logger&amp; logger = GetCurrentLogger();\r\n    WidgetWrapper wrapper(widget, logger);\r\n\r\n    DoSomethingWorker(wrapper, logger):\r\n}\r\n\r\nvoid DoSomethingWorker(\r\n    WidgetRefWrapper&amp; wrapper,\r\n    Logger&amp; logger)\r\n{\r\n    if (needs_toggling) {\r\n        wrapper.Toggle();\r\n    }\r\n}\r\n<\/pre>\n<p>Since the raw <code>widget<\/code> is never passed to the worker function, there is no way to access it. If you type <code>widget<\/code>, you get an undefined identifier.<\/p>\n<p>On the other hand, it also means that you have to pass all of the work you&#8217;ve done so far to the worker function. In this case, we pass the <code>logger<\/code>.<\/p>\n<p>Also, somebody might see that you split the work into two functions and say, &#8220;What&#8217;s the point of a function that is called in only one place? I can just inline it!&#8221; and now you&#8217;re back where you started.<\/p>\n<p>We can reuse the <a title=\"How can I prevent myself from accessing a lambda captured variable or a parameter after Im done with it?\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20211104-00\/?p=105872\"> clever hack \/ shameless abuse of the language<\/a> known as <code>hide_name<\/code>.<\/p>\n<pre>void DoSomething(Widget&amp; widget)\r\n{\r\n    Logger&amp; logger = GetCurrentLogger();\r\n    WidgetWrapper wrapper(widget, logger);\r\n\r\n    <span style=\"border: solid 1px currentcolor; border-bottom: none;\">\/\/ From now on, all access must be done through the wrapper.<\/span>\r\n    <span style=\"border: solid 1px currentcolor; border-top: none;\">hide_name widget;                                           <\/span>\r\n\r\n    if (needs_toggling) {\r\n        wrapper.Toggle();\r\n    }\r\n}\r\n<\/pre>\n<p><b>Previously in &#8220;clever hack or shameless abuse of the language&#8221;<\/b>: <a title=\"C++\/WinRT envy: Bringing thread switching tasks to C# (UWP edition)\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20190328-00\/?p=102368\"> Bringing thread switching tasks to C#<\/a>.<\/p>\n<p>\u00b9 Another case would be code that takes the inbound parameter and looks it up in some data structure to find a partner object, and we want all future operations to occur on the partner.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>You can shadow it with something useless.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-108775","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>You can shadow it with something useless.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/108775","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=108775"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/108775\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=108775"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=108775"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=108775"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}