< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Runtime.Collections.GenericHashtable<T1, T2>
Assembly: CoreWCF.NetNamedPipe
File(s): /home/runner/work/CoreWCF/CoreWCF/src/Common/src/CoreWCF/Runtime/Collections/GenericHashtable.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 56
Coverable lines: 56
Total lines: 142
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 26
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor()100%110%
Add(...)100%110%
Add(...)100%110%
Clear()100%110%
Contains(...)0%220%
ContainsKey(...)100%110%
CopyTo(...)0%880%
GetEnumerator()0%220%
Remove(...)0%220%
Remove(...)0%220%
TryGetValue(...)0%660%
System.Collections.IEnumerable.GetEnumerator()100%110%

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/Common/src/CoreWCF/Runtime/Collections/GenericHashtable.cs

#LineLine coverage
 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
 4using System;
 5using System.Collections;
 6using System.Collections.Generic;
 7using System.Linq;
 8
 9namespace CoreWCF.Runtime.Collections
 10{
 11    internal class GenericHashtable<TKey, TValue> : IDictionary<TKey, TValue>
 12    {
 13        private Hashtable _hashtable;
 14
 015        public GenericHashtable()
 16        {
 017            _hashtable = Hashtable.Synchronized(new Hashtable());
 018        }
 19
 20        public TValue this[TKey key]
 21        {
 22            get
 23            {
 024                if (key == null) throw new ArgumentNullException(nameof(key));
 025                if (!_hashtable.ContainsKey(key))
 26                {
 027                    throw new KeyNotFoundException();
 28                }
 29
 030                return (TValue)_hashtable[key];
 31            }
 032            set { _hashtable[key] = value; }
 33        }
 34
 035        public ICollection<TKey> Keys => _hashtable.Keys.Cast<TKey>().ToList();
 036        public ICollection<TValue> Values => _hashtable.Values.Cast<TValue>().ToList();
 037        public int Count => _hashtable.Count;
 038        public bool IsReadOnly => _hashtable.IsReadOnly;
 039        public void Add(TKey key, TValue value) => _hashtable.Add(key, value);
 040        public void Add(KeyValuePair<TKey, TValue> item) => _hashtable.Add(item.Key, item.Value);
 041        public void Clear() => _hashtable.Clear();
 42
 43        public bool Contains(KeyValuePair<TKey, TValue> item)
 44        {
 45            // Two reads from table need to be treated atomic otherwise Contains can return true
 46            // and this this[item.Key] might not find the key if a remove was in progress.
 047            lock (_hashtable.SyncRoot)
 48            {
 049                return _hashtable.Contains(item.Key) && this[item.Key].Equals(item.Value);
 50            }
 051        }
 52
 053        public bool ContainsKey(TKey key) => _hashtable.ContainsKey(key);
 54
 55        public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
 56        {
 057            if (array == null) throw new ArgumentNullException(nameof(array));
 058            if ((uint)arrayIndex > (uint)array.Length || array.Length - arrayIndex < Count)
 059                throw new ArgumentOutOfRangeException(nameof(arrayIndex));
 60
 061            foreach (DictionaryEntry entry in _hashtable)
 62            {
 063                var keyValuePair = new KeyValuePair<TKey, TValue>((TKey)entry.Key, (TValue)entry.Value);
 064                array[arrayIndex++] = keyValuePair;
 65            }
 066        }
 67
 68        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
 69        {
 070            foreach (DictionaryEntry entry in _hashtable)
 71            {
 072                yield return new KeyValuePair<TKey, TValue>((TKey)entry.Key, (TValue)entry.Value);
 73            }
 074        }
 75
 76        public bool Remove(TKey key)
 77        {
 078            lock (_hashtable.SyncRoot)
 79            {
 080                if (!ContainsKey(key))
 081                    return false;
 82
 083                _hashtable.Remove(key);
 084                return true;
 85            }
 086        }
 87
 88        public bool Remove(KeyValuePair<TKey, TValue> item)
 89        {
 90            // Need to wrap in lock otherwise the value could change between call to Contains(item) and
 91            // the remove call
 092            lock (_hashtable.SyncRoot)
 93            {
 094                if (!Contains(item))
 095                    return false;
 96
 097                _hashtable.Remove(item.Key);
 098                return true;
 99            }
 0100        }
 101
 102        public bool TryGetValue(TKey key, out TValue value)
 103        {
 104            // Lock free optimization when TValue is a value type
 0105            if (typeof(TValue).IsValueType)
 106            {
 0107                object obj = _hashtable[key];
 108                // Can only be null if not found, otherwise if found will always be a boxed value type
 0109                if (obj != null)
 110                {
 0111                    value = (TValue)obj;
 0112                    return true;
 113                }
 114
 0115                value = default;
 0116                return false;
 117            }
 118
 119            // When TValue is nullable, it might be in the Hashtable with a value of null so need to do
 120            // 2 lookups, one to see if it's there, another to get the (possibly null) value. Needs to
 121            // be atomic otherwise table could get modified between the 2 reads so using lock.
 0122            lock (_hashtable.SyncRoot)
 123            {
 124                // Need to call ContainsKey as value might be null so getting value and null checking
 125                // is insufficient.
 0126                if (!_hashtable.ContainsKey(key))
 127                {
 0128                    value = default;
 0129                    return false;
 130                }
 131
 0132                value = this[key];
 0133                return true;
 134            }
 0135        }
 136
 137        IEnumerator IEnumerable.GetEnumerator()
 138        {
 0139            return GetEnumerator();
 140        }
 141    }
 142}