question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Exceptions in indexers are always quietly ignored for IDictionary<T1,T2>

See original GitHub issue

Update: As @SeeminglyScience’s states below, ignoring of exceptions seems to be limited to indexing with types that implement IDictionary<T1, T2>, in which potential exceptions are deliberately avoided with .TryGetValue() calls.

An argument could be made that this behavior makes sense for the sake of symmetry with PowerShell’s regular, non-generic (ordered) hashtables, which themselves ignore non-existent keys.

It does amount to PowerShell modifying the behavior of .NET types in a non-obvious manner, however.


At least with Set-StrictMode -Version 3 or higher, using an array’s indexer with an out-of-bounds index results in a statement-terminating error.

The docs state with respect to version 3:

Prohibit out of bounds or unresolvable array indexes.

By contrast, other exceptions appear to be quietly ignored, irrespective of the effective Set-StrictMode setting.

A follow-up question is: should exceptions other than System.IndexOutOfRangeException and System.Collections.Generic.KeyNotFoundException always be surfaced?

Other types of exceptions are probably rare, but they do occur; e.g.:

# Note: Called  via .Item() instead of indexer syntax ([...]), 
# to ensure that the exception surfaces.
# Throws a System.ArgumentException
[Newtonsoft.Json.Linq.JObject]::Parse('{"foo":1}').Item([datetime]::now)

Steps to reproduce

Set-StrictMode -Version 3

# OK - exception (statement-terminating error)
{ (0,1)[2] } | should -Throw -ErrorId System.IndexOutOfRangeException

# Does NOT throw an exception, even though the underlying type does.
# Note: The non-generic [hashtable] type (@{ ... }) does NOT throw an exception,
#           but System.Collections.Generic.Dictionary<T, T> does.
{ $dt = [Collections.Generic.Dictionary[string, string]]::new(); $dt['nosuch'] } |
  Should -Throw -ErrorId System.Collections.Generic.KeyNotFoundException

Expected behavior

Both tests should pass.

Actual behavior

The 2nd test fails:

Expected an exception, to be thrown, but no exception was thrown.

That is, the exception that occurs in the [System.Collections.Generic.Dictionary] indexer is quietly ignored.

You can surface it if you call the underlying .Item() method (parameterized property) directly:

$dt = [Collections.Generic.Dictionary[string, string]]::new(); $dt.Item('nosuch')

This reports the following error (ultimately a System.Collections.Generic.KeyNotFoundException exception):

Exception getting "Item": "The given key 'nosuch' was not present in the dictionary"

Environment data

PowerShell Core 7.0.0-preview.4

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:10 (5 by maintainers)

github_iconTop GitHub Comments

3reactions
SeeminglySciencecommented, Oct 1, 2019

@mklement0 Dictionary<,> does though:

PS> $dt = [Collections.Generic.Dictionary[string, string]]::new()
PS> $dt['what']
# nothing
PS> $dt.get_Item('what')
Exception calling "get_Item" with "1" argument(s): "The given key 'what' was not present in the dictionary."
At line:1 char:1
+ $dt.get_Item('what')
+ ~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : KeyNotFoundException
1reaction
SeeminglySciencecommented, Oct 1, 2019

Yeah IDictionary<,> follows a different pattern, it does TryGetValue instead:

https://github.com/PowerShell/PowerShell/blob/d8eca6a729a94c626bc161f94c4e694451d7e4da/src/System.Management.Automation/engine/runtime/Binding/Binders.cs#L4130-L4137

Apparently JObject is also IDictionary<,>.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Performance Tips · The Julia Language
Performance Tips. In the following sections, we briefly go through a few techniques that can help make your Julia code run as fast...
Read more >
TECHNICAL NOTES
INDEX * SPIRES Technical Notes +1 A Brief Explanation About this Document 1 Sorting Records in SPIRES; SPISORT 1.1 An Overview of Record-Sorting...
Read more >
The OCaml system release 5.0
explicit handling of pointers: the OCaml compiler silently introduces pointers ... You can ignore the first two lines of the error message.
Read more >
tifffile/tifffile/tifffile.py at master · cgohlke/tifffile
Metadata contained in a separate NDTiff.index binary file defines the ... is None: byteorder = data.dtype.byteorder # type: ignore except Exception: ...
Read more >
MOSEK Command Line Tools - Documentation
Empty lines and lines starting from a % sign are ignored. • Each line contains a valid MOSEK parameter name followed by its...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found