Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Kyte <alexmkyte@gmail.com>2017-10-02 21:59:16 +0300
committerMarek Safar <marek.safar@gmail.com>2017-10-06 12:35:17 +0300
commit410bb8a57e23a901ea47d8a74f88a20972de423d (patch)
treef11942965e8a275fbd22bde087cf67785aa97ea8
parent74a87af7f580c59f524f79508e4ad32ccff0870a (diff)
[runtime] Fix Empty generic enumerator equality
On the CLR, two enumerators containing zero elements will have reference equality if they are inflated with the same generic type. If comparing two enumerators which are not inflated (Array.Empty, for instance), they are not equal when they contain zero elements. This reference equality behavior is not compatible with treating the enumerators as structs, as value types will not have reference equality.
-rw-r--r--mcs/class/corlib/System/Array.cs37
-rw-r--r--mcs/class/corlib/Test/System/ArrayTest.cs14
2 files changed, 50 insertions, 1 deletions
diff --git a/mcs/class/corlib/System/Array.cs b/mcs/class/corlib/System/Array.cs
index d699446f2b5..91424bc6f8f 100644
--- a/mcs/class/corlib/System/Array.cs
+++ b/mcs/class/corlib/System/Array.cs
@@ -68,7 +68,10 @@ namespace System
internal IEnumerator<T> InternalArray__IEnumerable_GetEnumerator<T> ()
{
- return new InternalEnumerator<T> (this);
+ if (Length == 0)
+ return EmptyInternalEnumerator<T>.Value;
+ else
+ return new InternalEnumerator<T> (this);
}
internal void InternalArray__ICollection_Clear ()
@@ -271,6 +274,38 @@ namespace System
}
}
+ internal class EmptyInternalEnumerator<T> : IEnumerator<T>
+ {
+ public static readonly EmptyInternalEnumerator<T> Value = new EmptyInternalEnumerator<T> ();
+
+ public void Dispose ()
+ {
+ return;
+ }
+
+ public bool MoveNext ()
+ {
+ return false;
+ }
+
+ public T Current {
+ get {
+ throw new InvalidOperationException ("Enumeration has not started. Call MoveNext");
+ }
+ }
+
+ object IEnumerator.Current {
+ get {
+ return Current;
+ }
+ }
+
+ void IEnumerator.Reset ()
+ {
+ return;
+ }
+ }
+
// InternalCall Methods
[MethodImplAttribute (MethodImplOptions.InternalCall)]
extern int GetRank ();
diff --git a/mcs/class/corlib/Test/System/ArrayTest.cs b/mcs/class/corlib/Test/System/ArrayTest.cs
index 0a04041aea3..36db33d6352 100644
--- a/mcs/class/corlib/Test/System/ArrayTest.cs
+++ b/mcs/class/corlib/Test/System/ArrayTest.cs
@@ -3693,6 +3693,20 @@ public class ArrayTest
Assert.AreEqual (3, c.Counter);
}
+ [Test]
+ public void EnumeratorsEquality ()
+ {
+ int [] normalBase = new int [0];
+ IEnumerable<int> specialBase = new int [0];
+
+ var firstSpecial = specialBase.GetEnumerator ();
+ var secondSpecial = specialBase.GetEnumerator ();
+ var firstNormal = normalBase.GetEnumerator ();
+ var secondNormal = normalBase.GetEnumerator ();
+
+ Assert.IsFalse (object.ReferenceEquals (firstNormal, secondNormal));
+ Assert.IsTrue (object.ReferenceEquals (firstSpecial, secondSpecial));
+ }
[Test]
public void JaggedArrayCtor ()