Nullable: System.Runtime.InteropServices.CustomMarshalers/WindowsRuntime (#23930)
[platform/upstream/coreclr.git] / src / System.Private.CoreLib / src / System / Runtime / InteropServices / WindowsRuntime / DictionaryToMapAdapter.cs
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 #nullable enable
6 using System.Collections.Generic;
7 using System.Collections.ObjectModel;
8 using System.Diagnostics;
9 using Internal.Runtime.CompilerServices;
10
11 namespace System.Runtime.InteropServices.WindowsRuntime
12 {
13     // This is a set of stub methods implementing the support for the IMap`2 interface on managed
14     // objects that implement IDictionary`2. Used by the interop mashaling infrastructure.
15     //
16     // The methods on this class must be written VERY carefully to avoid introducing security holes.
17     // That's because they are invoked with special "this"! The "this" object
18     // for all of these methods are not DictionaryToMapAdapter objects. Rather, they are of type
19     // IDictionary<K, V>. No actual DictionaryToMapAdapter object is ever instantiated. Thus, you will
20     // see a lot of expressions that cast "this" to "IDictionary<K, V>". 
21     internal sealed class DictionaryToMapAdapter
22     {
23         private DictionaryToMapAdapter()
24         {
25             Debug.Fail("This class is never instantiated");
26         }
27
28         // V Lookup(K key)
29         internal V Lookup<K, V>(K key)
30         {
31             IDictionary<K, V> _this = Unsafe.As<IDictionary<K, V>>(this);
32             V value;
33             bool keyFound = _this.TryGetValue(key, out value);
34
35             if (!keyFound)
36             {
37                 Debug.Assert(key != null);
38                 Exception e = new KeyNotFoundException(SR.Format(SR.Arg_KeyNotFoundWithKey, key.ToString()));
39                 e.HResult = HResults.E_BOUNDS;
40                 throw e;
41             }
42
43             return value;
44         }
45
46         // uint Size { get }
47         internal uint Size<K, V>()
48         {
49             IDictionary<K, V> _this = Unsafe.As<IDictionary<K, V>>(this);
50             return (uint)_this.Count;
51         }
52
53         // bool HasKey(K key)
54         internal bool HasKey<K, V>(K key)
55         {
56             IDictionary<K, V> _this = Unsafe.As<IDictionary<K, V>>(this);
57             return _this.ContainsKey(key);
58         }
59
60         // IMapView<K, V> GetView()
61         internal IReadOnlyDictionary<K, V> GetView<K, V>()
62         {
63             IDictionary<K, V> _this = Unsafe.As<IDictionary<K, V>>(this);
64             Debug.Assert(_this != null);
65
66             // Note: This dictionary is not really read-only - you could QI for a modifiable
67             // dictionary.  We gain some perf by doing this.  We believe this is acceptable.
68             if (!(_this is IReadOnlyDictionary<K, V> roDictionary))
69             {
70                 roDictionary = new ReadOnlyDictionary<K, V>(_this);
71             }
72             return roDictionary;
73         }
74
75         // bool Insert(K key, V value)
76         internal bool Insert<K, V>(K key, V value)
77         {
78             IDictionary<K, V> _this = Unsafe.As<IDictionary<K, V>>(this);
79             bool replacing = _this.ContainsKey(key);
80             _this[key] = value;
81             return replacing;
82         }
83
84         // void Remove(K key)
85         internal void Remove<K, V>(K key)
86         {
87             IDictionary<K, V> _this = Unsafe.As<IDictionary<K, V>>(this);
88             bool removed = _this.Remove(key);
89
90             if (!removed)
91             {
92                 Debug.Assert(key != null);
93                 Exception e = new KeyNotFoundException(SR.Format(SR.Arg_KeyNotFoundWithKey, key.ToString()));
94                 e.HResult = HResults.E_BOUNDS;
95                 throw e;
96             }
97         }
98
99         // void Clear()
100         internal void Clear<K, V>()
101         {
102             IDictionary<K, V> _this = Unsafe.As<IDictionary<K, V>>(this);
103             _this.Clear();
104         }
105     }
106 }