The Labs \ Source Viewer \ SSCLI \ System.Collections \ NodeKeyValueEnumerator

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. /*============================================================
  16. **
  17. ** Class:  ListDictionaryInternal
  18. **
  19. **
  20. ** Purpose: List for exceptions.
  21. **
  22. **
  23. ===========================================================*/
  24. namespace System.Collections
  25. {
  26.     /// This is a simple implementation of IDictionary using a singly linked list. This
  27.     /// will be smaller and faster than a Hashtable if the number of elements is 10 or less.
  28.     /// This should not be used if performance is important for large numbers of elements.
  29.     [Serializable()]
  30.     internal class ListDictionaryInternal : IDictionary
  31.     {
  32.         DictionaryNode head;
  33.         int version;
  34.         int count;
  35.         [NonSerialized()]
  36.         private object _syncRoot;
  37.        
  38.         public ListDictionaryInternal()
  39.         {
  40.         }
  41.        
  42.         public object this[object key]
  43.         {
  44.             get {
  45.                 if (key == null) {
  46.                     throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
  47.                 }
  48.                 DictionaryNode node = head;
  49.                
  50.                 while (node != null) {
  51.                     if (node.key.Equals(key)) {
  52.                         return node.value;
  53.                     }
  54.                     node = node.next;
  55.                 }
  56.                 return null;
  57.             }
  58.             set {
  59.                 if (key == null) {
  60.                     throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
  61.                 }
  62.                
  63.                 if (!key.GetType().IsSerializable)
  64.                     throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), "key");
  65.                
  66.                 if ((value != null) && (!value.GetType().IsSerializable))
  67.                     throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), "value");
  68.                
  69.                 version++;
  70.                 DictionaryNode last = null;
  71.                 DictionaryNode node;
  72.                 for (node = head; node != null; node = node.next) {
  73.                     if (node.key.Equals(key)) {
  74.                         break;
  75.                     }
  76.                     last = node;
  77.                 }
  78.                 if (node != null) {
  79.                     // Found it
  80.                     node.value = value;
  81.                     return;
  82.                 }
  83.                 // Not found, so add a new one
  84.                 DictionaryNode newNode = new DictionaryNode();
  85.                 newNode.key = key;
  86.                 newNode.value = value;
  87.                 if (last != null) {
  88.                     last.next = newNode;
  89.                 }
  90.                 else {
  91.                     head = newNode;
  92.                 }
  93.                 count++;
  94.             }
  95.         }
  96.        
  97.         public int Count {
  98.             get { return count; }
  99.         }
  100.        
  101.         public ICollection Keys {
  102.             get { return new NodeKeyValueCollection(this, true); }
  103.         }
  104.        
  105.         public bool IsReadOnly {
  106.             get { return false; }
  107.         }
  108.        
  109.         public bool IsFixedSize {
  110.             get { return false; }
  111.         }
  112.        
  113.         public bool IsSynchronized {
  114.             get { return false; }
  115.         }
  116.        
  117.         public object SyncRoot {
  118.             get {
  119.                 if (_syncRoot == null) {
  120.                     System.Threading.Interlocked.CompareExchange(ref _syncRoot, new object(), null);
  121.                 }
  122.                 return _syncRoot;
  123.             }
  124.         }
  125.        
  126.         public ICollection Values {
  127.             get { return new NodeKeyValueCollection(this, false); }
  128.         }
  129.        
  130.         public void Add(object key, object value)
  131.         {
  132.             if (key == null) {
  133.                 throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
  134.             }
  135.            
  136.             if (!key.GetType().IsSerializable)
  137.                 throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), "key");
  138.            
  139.             if ((value != null) && (!value.GetType().IsSerializable))
  140.                 throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), "value");
  141.            
  142.             version++;
  143.             DictionaryNode last = null;
  144.             DictionaryNode node;
  145.             for (node = head; node != null; node = node.next) {
  146.                 if (node.key.Equals(key)) {
  147.                     throw new ArgumentException(Environment.GetResourceString("Argument_AddingDuplicate__", node.key, key));
  148.                 }
  149.                 last = node;
  150.             }
  151.             if (node != null) {
  152.                 // Found it
  153.                 node.value = value;
  154.                 return;
  155.             }
  156.             // Not found, so add a new one
  157.             DictionaryNode newNode = new DictionaryNode();
  158.             newNode.key = key;
  159.             newNode.value = value;
  160.             if (last != null) {
  161.                 last.next = newNode;
  162.             }
  163.             else {
  164.                 head = newNode;
  165.             }
  166.             count++;
  167.         }
  168.        
  169.         public void Clear()
  170.         {
  171.             count = 0;
  172.             head = null;
  173.             version++;
  174.         }
  175.        
  176.         public bool Contains(object key)
  177.         {
  178.             if (key == null) {
  179.                 throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
  180.             }
  181.             for (DictionaryNode node = head; node != null; node = node.next) {
  182.                 if (node.key.Equals(key)) {
  183.                     return true;
  184.                 }
  185.             }
  186.             return false;
  187.         }
  188.        
  189.         public void CopyTo(Array array, int index)
  190.         {
  191.             if (array == null)
  192.                 throw new ArgumentNullException("array");
  193.            
  194.             if (array.Rank != 1)
  195.                 throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"));
  196.            
  197.             if (index < 0)
  198.                 throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  199.            
  200.             if (array.Length - index < this.Count)
  201.                 throw new ArgumentException(Environment.GetResourceString("ArgumentOutOfRange_Index"), "index");
  202.            
  203.             for (DictionaryNode node = head; node != null; node = node.next) {
  204.                 array.SetValue(new DictionaryEntry(node.key, node.value), index);
  205.                 index++;
  206.             }
  207.         }
  208.        
  209.         public IDictionaryEnumerator GetEnumerator()
  210.         {
  211.             return new NodeEnumerator(this);
  212.         }
  213.        
  214.         IEnumerator IEnumerable.GetEnumerator()
  215.         {
  216.             return new NodeEnumerator(this);
  217.         }
  218.        
  219.         public void Remove(object key)
  220.         {
  221.             if (key == null) {
  222.                 throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
  223.             }
  224.             version++;
  225.             DictionaryNode last = null;
  226.             DictionaryNode node;
  227.             for (node = head; node != null; node = node.next) {
  228.                 if (node.key.Equals(key)) {
  229.                     break;
  230.                 }
  231.                 last = node;
  232.             }
  233.             if (node == null) {
  234.                 return;
  235.             }
  236.             if (node == head) {
  237.                 head = node.next;
  238.             }
  239.             else {
  240.                 last.next = node.next;
  241.             }
  242.             count--;
  243.         }
  244.        
  245.         private class NodeEnumerator : IDictionaryEnumerator
  246.         {
  247.             ListDictionaryInternal list;
  248.             DictionaryNode current;
  249.             int version;
  250.             bool start;
  251.            
  252.            
  253.             public NodeEnumerator(ListDictionaryInternal list)
  254.             {
  255.                 this.list = list;
  256.                 version = list.version;
  257.                 start = true;
  258.                 current = null;
  259.             }
  260.            
  261.             public object Current {
  262.                 get { return Entry; }
  263.             }
  264.            
  265.             public DictionaryEntry Entry {
  266.                 get {
  267.                     if (current == null) {
  268.                         throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
  269.                     }
  270.                     return new DictionaryEntry(current.key, current.value);
  271.                 }
  272.             }
  273.            
  274.             public object Key {
  275.                 get {
  276.                     if (current == null) {
  277.                         throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
  278.                     }
  279.                     return current.key;
  280.                 }
  281.             }
  282.            
  283.             public object Value {
  284.                 get {
  285.                     if (current == null) {
  286.                         throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
  287.                     }
  288.                     return current.value;
  289.                 }
  290.             }
  291.            
  292.             public bool MoveNext()
  293.             {
  294.                 if (version != list.version) {
  295.                     throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumFailedVersion"));
  296.                 }
  297.                 if (start) {
  298.                     current = list.head;
  299.                     start = false;
  300.                 }
  301.                 else {
  302.                     if (current != null) {
  303.                         current = current.next;
  304.                     }
  305.                 }
  306.                 return (current != null);
  307.             }
  308.            
  309.             public void Reset()
  310.             {
  311.                 if (version != list.version) {
  312.                     throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumFailedVersion"));
  313.                 }
  314.                 start = true;
  315.                 current = null;
  316.             }
  317.            
  318.         }
  319.        
  320.        
  321.         private class NodeKeyValueCollection : ICollection
  322.         {
  323.             ListDictionaryInternal list;
  324.             bool isKeys;
  325.            
  326.             public NodeKeyValueCollection(ListDictionaryInternal list, bool isKeys)
  327.             {
  328.                 this.list = list;
  329.                 this.isKeys = isKeys;
  330.             }
  331.            
  332.             void ICollection.CopyTo(Array array, int index)
  333.             {
  334.                 if (array == null)
  335.                     throw new ArgumentNullException("array");
  336.                 if (array.Rank != 1)
  337.                     throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"));
  338.                 if (index < 0)
  339.                     throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  340.                 if (array.Length - index < list.Count)
  341.                     throw new ArgumentException(Environment.GetResourceString("ArgumentOutOfRange_Index"), "index");
  342.                 for (DictionaryNode node = list.head; node != null; node = node.next) {
  343.                     array.SetValue(isKeys ? node.key : node.value, index);
  344.                     index++;
  345.                 }
  346.             }
  347.            
  348.             int ICollection.Count {
  349.                 get {
  350.                     int count = 0;
  351.                     for (DictionaryNode node = list.head; node != null; node = node.next) {
  352.                         count++;
  353.                     }
  354.                     return count;
  355.                 }
  356.             }
  357.            
  358.             bool ICollection.IsSynchronized {
  359.                 get { return false; }
  360.             }
  361.            
  362.             object ICollection.SyncRoot {
  363.                 get { return list.SyncRoot; }
  364.             }
  365.            
  366.             IEnumerator IEnumerable.GetEnumerator()
  367.             {
  368.                 return new NodeKeyValueEnumerator(list, isKeys);
  369.             }
  370.            
  371.            
  372.             private class NodeKeyValueEnumerator : IEnumerator
  373.             {
  374.                 ListDictionaryInternal list;
  375.                 DictionaryNode current;
  376.                 int version;
  377.                 bool isKeys;
  378.                 bool start;
  379.                
  380.                 public NodeKeyValueEnumerator(ListDictionaryInternal list, bool isKeys)
  381.                 {
  382.                     this.list = list;
  383.                     this.isKeys = isKeys;
  384.                     this.version = list.version;
  385.                     this.start = true;
  386.                     this.current = null;
  387.                 }
  388.                
  389.                 public object Current {
  390.                     get {
  391.                         if (current == null) {
  392.                             throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
  393.                         }
  394.                         return isKeys ? current.key : current.value;
  395.                     }
  396.                 }
  397.                
  398.                 public bool MoveNext()
  399.                 {
  400.                     if (version != list.version) {
  401.                         throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumFailedVersion"));
  402.                     }
  403.                     if (start) {
  404.                         current = list.head;
  405.                         start = false;
  406.                     }
  407.                     else {
  408.                         if (current != null) {
  409.                             current = current.next;
  410.                         }
  411.                     }
  412.                     return (current != null);
  413.                 }
  414.                
  415.                 public void Reset()
  416.                 {
  417.                     if (version != list.version) {
  418.                         throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumFailedVersion"));
  419.                     }
  420.                     start = true;
  421.                     current = null;
  422.                 }
  423.             }
  424.         }
  425.        
  426.         [Serializable()]
  427.         private class DictionaryNode
  428.         {
  429.             public object key;
  430.             public object value;
  431.             public DictionaryNode next;
  432.         }
  433.     }
  434. }

Developer Fusion