{"id":109146,"date":"2023-12-14T07:00:00","date_gmt":"2023-12-14T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=109146"},"modified":"2023-12-15T09:42:53","modified_gmt":"2023-12-15T17:42:53","slug":"20231214-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20231214-00\/?p=109146","title":{"rendered":"How do I specify an optional parameter to a Windows Runtime method?"},"content":{"rendered":"<p>In C++, you can specify optional parameters with <code>std::optional&lt;T&gt;<\/code>.\u00b9<\/p>\n<pre>void MyMethod(\r\n    std::optional&lt;int&gt; const&amp; a,\r\n    std::optional&lt;int&gt; const&amp; b);\r\n\r\nMyMethod(1, 2);                       \/\/ both parameters provided\r\nMyMethod(1, std::nullopt);            \/\/ only first parameter provided\r\nMyMethod(std::nullopt, 2);            \/\/ only second parameter provided\r\nMyMethod(std::nullopt, std::nullopt); \/\/ neither parameter provided\r\n<\/pre>\n<p>In C#, you can use <code>Nullable&lt;T&gt;<\/code>. Rust uses <code>Option&lt;T&gt;<\/code>. In JavaScript, you can pass <code>null<\/code>. What about the Windows Runtime?<\/p>\n<p>First of all, this was a trick question.<\/p>\n<p>The C# and JavaScript versions aren&#8217;t actually optional parameters. The C# <code>Nullable&lt;T&gt;<\/code> and JavaScript cases do not distinguish between passing <code>null<\/code> to mean &#8220;I am not passing this parameter&#8221; and passing <code>null<\/code> to mean &#8220;I am passing a parameter, and it is <code>null<\/code>.&#8221; C++ distinguishes between the two cases:<\/p>\n<pre>void MyMethod(\r\n    std::optional&lt;const char*&gt; const&amp; a);\r\n\r\nMyMethod(nullptr);      \/\/ We are passing a null pointer\r\nMyMethod(std::nullopt); \/\/ We aren't passing anything\r\n<\/pre>\n<p>Let&#8217;s continue the deception and assume that any passed parameter is not null. (In other words, passing null is equivalent to not passing anything.)<\/p>\n<p>For reference types, you can use null as the sentinel value that means &#8220;no value&#8221;.<\/p>\n<pre>\/\/ IDL\r\nstatic runtimeclass MyClass\r\n{\r\n    static void MyMethod(MyClass a);\r\n}\r\n<\/pre>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th>Projection<\/th>\n<th>Reference consumer<br \/>\nAPI producer<\/th>\n<th>Reference producer<br \/>\nAPI consumer<\/th>\n<\/tr>\n<tr>\n<td>C++\/WinRT<\/td>\n<td style=\"font-size: 80%;\"><code>MyMethod(MyClass a) {\u00a0\u00a0<\/code><br \/>\n<code>\u00a0\u00a0if (a) use(a);\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/code><br \/>\n<code>\u00a0\u00a0else use_nothing();\u00a0}<\/code><\/td>\n<td><code>MyMethod(a);<\/code><br \/>\n<code>MyMethod(nullptr);<\/code><\/td>\n<\/tr>\n<tr>\n<td>C++\/CX<\/td>\n<td style=\"font-size: 80%;\"><code>MyMethod(MyClass^ a) {\u00a0<\/code><br \/>\n<code>\u00a0\u00a0if (a) use(a);\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/code><br \/>\n<code>\u00a0\u00a0else use_nothing(); }<\/code><\/td>\n<td><code>MyMethod(a);<\/code><br \/>\n<code>MyMethod(nullptr);<\/code><\/td>\n<\/tr>\n<tr>\n<td>C#<\/td>\n<td style=\"font-size: 80%;\"><code>MyMethod(MyClass a) {\u00a0\u00a0<\/code><br \/>\n<code>\u00a0\u00a0if (a != null) use(a);<\/code><br \/>\n<code>\u00a0\u00a0else use_nothing(); }<\/code><\/td>\n<td><code>MyMethod(a);<\/code><br \/>\n<code>MyMethod(null);<\/code><\/td>\n<\/tr>\n<tr>\n<td>JavaScript<\/td>\n<td style=\"font-size: 80%;\"><code>function myMethod(a) {\u00a0\u00a0<\/code><br \/>\n<code>\u00a0\u00a0if (a) use(a);\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/code><br \/>\n<code>\u00a0\u00a0else use_nothing(); }\u00a0<\/code><\/td>\n<td><code>myMethod(a);<\/code><br \/>\n<code>myMethod(null);<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>For value types, you can use the <code>IReference&lt;T&gt;<\/code> interface to add a null value to a value type:<\/p>\n<pre>\/\/ IDL\r\nstatic runtimeclass MyClass\r\n{\r\n    static void MyMethod(Windows.Foundation.IReference&lt;Int32&gt; a);\r\n}\r\n<\/pre>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th>Projection<\/th>\n<th>Projects as<\/th>\n<th>IReference consumer<br \/>\nAPI producer<\/th>\n<th>IReference producer<br \/>\nAPI consumer<\/th>\n<\/tr>\n<tr>\n<td>C++\/WinRT<\/td>\n<td><code>IReference&lt;int&gt;<\/code><\/td>\n<td style=\"font-size: 80%;\"><code>MyMethod(IReference&lt;int&gt; a) {<\/code><br \/>\n<code>\u00a0\u00a0if (a) use(a.Value());\u00a0\u00a0\u00a0\u00a0\u00a0<\/code><br \/>\n<code>\u00a0\u00a0else use_nothing();\u00a0}\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/code><\/td>\n<td><code>MyMethod(42);<\/code><br \/>\n<code>MyMethod(nullptr);<\/code><\/td>\n<\/tr>\n<tr>\n<td>C++\/CX<\/td>\n<td><code>IBox&lt;int&gt;<\/code><\/td>\n<td style=\"font-size: 80%;\"><code>MyMethod(IBox&lt;int&gt;^ a) {<\/code><br \/>\n<code>\u00a0\u00a0if (a) use(a-&gt;Value);\u00a0<\/code><br \/>\n<code>\u00a0\u00a0else use_nothing(); }\u00a0<\/code><\/td>\n<td><code>MyMethod(42);<\/code><br \/>\n<code>MyMethod(nullptr);<\/code><\/td>\n<\/tr>\n<tr>\n<td>C#<\/td>\n<td><code>Nullable&lt;int&gt;<\/code><\/td>\n<td style=\"font-size: 80%;\"><code>MyMethod(Nullable&lt;int&gt; a) {<\/code><br \/>\n<code>\u00a0\u00a0if (a) use(a.Value);\u00a0\u00a0\u00a0\u00a0\u00a0<\/code><br \/>\n<code>\u00a0\u00a0else use_nothing(); }\u00a0\u00a0\u00a0\u00a0<\/code><\/td>\n<td><code>MyMethod(42);<\/code><br \/>\n<code>MyMethod(null);<\/code><\/td>\n<\/tr>\n<tr>\n<td>JavaScript<\/td>\n<td><code>Object<\/code><\/td>\n<td style=\"font-size: 80%;\"><code>function myMethod(a) {\u00a0\u00a0<\/code><br \/>\n<code>\u00a0\u00a0if (a == null) use(a);<\/code><br \/>\n<code>\u00a0\u00a0else use_nothing(); }\u00a0<\/code><\/td>\n<td><code>myMethod(42);<\/code><br \/>\n<code>myMethod(null);<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>There&#8217;s one problem though: What if I want an optional string? Do I use the reference pattern or the value pattern?<\/p>\n<p>It turns out the answer is &#8220;no&#8221;.<\/p>\n<p>We&#8217;ll look at this some more next time.<\/p>\n<p>\u00b9 Note that optional parameters are not the same thing as default parameters. Default parameters are parameters which the compiler fills in for you if you leave them out of the parameter list. Optional parameters are parameters where you can pass a value, or you can say &#8220;No value here.&#8221;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>There is no way to express explicit optionality, but there are implicit ways.<\/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-109146","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>There is no way to express explicit optionality, but there are implicit ways.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/109146","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=109146"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/109146\/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=109146"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=109146"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=109146"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}