MostlySingletonList.cs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.ServiceModel
  5. {
  6. using System.Collections.Generic;
  7. using System.IdentityModel;
  8. // Embed this struct in a class to represent a field of that class
  9. // that is logically a list, but contains just one item in all but
  10. // the rarest of scenarios. When this class must be passed around
  11. // in internal APIs, use it as a ref parameter.
  12. struct MostlySingletonList<T> where T : class
  13. {
  14. int count;
  15. T singleton;
  16. List<T> list;
  17. public T this[int index]
  18. {
  19. get
  20. {
  21. if (this.list == null)
  22. {
  23. EnsureValidSingletonIndex(index);
  24. return this.singleton;
  25. }
  26. else
  27. {
  28. return this.list[index];
  29. }
  30. }
  31. }
  32. public int Count
  33. {
  34. get { return this.count; }
  35. }
  36. public void Add(T item)
  37. {
  38. if (this.list == null)
  39. {
  40. if (this.count == 0)
  41. {
  42. this.singleton = item;
  43. this.count = 1;
  44. return;
  45. }
  46. this.list = new List<T>();
  47. this.list.Add(this.singleton);
  48. this.singleton = null;
  49. }
  50. this.list.Add(item);
  51. this.count++;
  52. }
  53. static bool Compare(T x, T y)
  54. {
  55. return x == null ? y == null : x.Equals(y);
  56. }
  57. public bool Contains(T item)
  58. {
  59. return IndexOf(item) >= 0;
  60. }
  61. void EnsureValidSingletonIndex(int index)
  62. {
  63. if (this.count != 1 || index != 0)
  64. {
  65. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("index"));
  66. }
  67. }
  68. bool MatchesSingleton(T item)
  69. {
  70. return this.count == 1 && Compare(this.singleton, item);
  71. }
  72. public int IndexOf(T item)
  73. {
  74. if (this.list == null)
  75. {
  76. return MatchesSingleton(item) ? 0 : -1;
  77. }
  78. else
  79. {
  80. return this.list.IndexOf(item);
  81. }
  82. }
  83. public bool Remove(T item)
  84. {
  85. if (this.list == null)
  86. {
  87. if (MatchesSingleton(item))
  88. {
  89. this.singleton = null;
  90. this.count = 0;
  91. return true;
  92. }
  93. else
  94. {
  95. return false;
  96. }
  97. }
  98. else
  99. {
  100. bool result = this.list.Remove(item);
  101. if (result)
  102. {
  103. this.count--;
  104. }
  105. return result;
  106. }
  107. }
  108. public void RemoveAt(int index)
  109. {
  110. if (this.list == null)
  111. {
  112. EnsureValidSingletonIndex(index);
  113. this.singleton = null;
  114. this.count = 0;
  115. }
  116. else
  117. {
  118. this.list.RemoveAt(index);
  119. this.count--;
  120. }
  121. }
  122. }
  123. }