{"id":103588,"date":"2020-03-25T07:00:00","date_gmt":"2020-03-25T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=103588"},"modified":"2020-03-25T07:58:29","modified_gmt":"2020-03-25T14:58:29","slug":"20200325-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20200325-00\/?p=103588","title":{"rendered":"How can I check whether a Windows Runtime object supports a member before I try to use it?"},"content":{"rendered":"<p>Last time, we saw that <a href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20200324-00\/?p=103586\"> an invalid cast exception can mean that you tried to use a class member that isn&#8217;t supported by the current operating system<\/a>. What can you do to avoid this problem?<\/p>\n<p>You might be running into this problem because your program is running on a version of Windows that you never intended to support. For example, your program is totally dependent upon some feature added in Windows 10 version 1903, and there&#8217;s no point trying to run it on anything earlier. You can go to your manifest and set the <code>Min\u00adVersion<\/code> in your <code>Target\u00adDevice\u00adFamily<\/code> element to the minimum version that supports the thing you need. Your application will be deployed only to systems that satisfy your manifest&#8217;s minimum requirements.<\/p>\n<p>You can get the minimum version from MSDN under <b>Additional features and requirements<\/b>:<\/p>\n<table style=\"border-collapse: collapse;\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td style=\"border: solid 1px #ccc;\">Device family<\/td>\n<td style=\"border: solid 1px #ccc;\">Windows 10, version 1803 (introduced v<u>10.0.17134.0<\/u>)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>In this case, the magic number to put in your manifest is 10.0.17134.0. Naturally, if you have many minimum requirements, then the one you pick for your manifest is the highest.<\/p>\n<pre>&lt;TargetDeviceFamily Name=\"Windows.Universal\"\r\n    MinVersion=\"10.0.<u>17134<\/u>.0\"\r\n    MaxVersionTested=\"10.0.18362.0\" \/&gt;\r\n<\/pre>\n<p>Another option is to perform a runtime check before trying to use the possibly-nonexistent member. The most direct way is to check specifically for the thing:<\/p>\n<pre>\/\/ C#\r\nif (<a href=\"https:\/\/docs.microsoft.com\/en-us\/uwp\/api\/Windows.Foundation.Metadata.ApiInformation\">ApiInformation<\/a>.IsMethodPresent(\"MyNamespace.MyClass\", \"SomeMember\"))\r\n{\r\n  \/\/ There is a method called SomeMember\r\n  myObject.SomeMember();\r\n}\r\n<\/pre>\n<p>If overloads were added at different times, you will need to use the check that takes an arity.<\/p>\n<pre>if (<a href=\"https:\/\/docs.microsoft.com\/en-us\/uwp\/api\/Windows.Foundation.Metadata.ApiInformation\">ApiInformation<\/a>.IsMethodPresent(\"MyNamespace.MyClass\", \"SomeMember\", 1))\r\n{\r\n  \/\/ it is okay to call the overload of the SomeMember method with 1 parameter\r\n  myObject.SomeMember(true);\r\n}\r\n<\/pre>\n<p>You can use C#&#8217;s <code>nameof<\/code> operator and <code>Type.FullName<\/code> property to avoid hard-coding strings. In C++\/WinRT, you can use <code>winrt::name_of&lt;T&gt;()<\/code>.<\/p>\n<p>You can also check for the existence of properties, and even narrow your check to read-only properties or writable properties.<\/p>\n<p>Another option for the runtime check is to check for the presence of the corresponding contract that introduced support for it. This information is also provided in MSDN under <b>Additional features and requirements<\/b>:<\/p>\n<table style=\"border-collapse: collapse;\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td style=\"border: solid 1px #ccc;\">API contract<\/td>\n<td style=\"border: solid 1px #ccc;\">Windows.Foundation.UniversalApiContract (introduced v6)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The contract name and version are what you pass to the <code>Is\u00adApi\u00adContract\u00adPresent<\/code> method.<\/p>\n<pre>\/\/ C#\r\nif (ApiInformation.IsApiContractPresent(\r\n    \"Windows.Foundation.UniversalApiContract\", 6))\r\n{\r\n  \/\/ it is okay to use things that were introduced in\r\n  \/\/ Windows.Foundation.UniversalApiContract version 6.\r\n}\r\n<\/pre>\n<p><b>Bonus chatter<\/b>: What about JavaScript? In JavaScript, an attempt to read a nonexistent member succeeds but returns <code>undefined<\/code>. This behavior is consistent with the overall design of the JavaScript language.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>You can sniff at the metadata.<\/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-103588","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>You can sniff at the metadata.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/103588","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=103588"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/103588\/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=103588"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=103588"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=103588"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}