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.
5 /*============================================================
8 ** Purpose: Base class which can be used to access any array
10 ===========================================================*/
14 using System.Collections;
15 using System.Collections.Generic;
16 using System.Collections.ObjectModel;
17 using System.Runtime.InteropServices;
18 using System.Runtime.CompilerServices;
19 using System.Runtime.ConstrainedExecution;
20 using System.Runtime.Versioning;
21 using System.Security;
22 using System.Security.Permissions;
23 using System.Diagnostics.Contracts;
25 // Note that we make a T[] (single-dimensional w/ zero as the lower bound) implement both
26 // IList<U> and IReadOnlyList<U>, where T : U dynamically. See the SZArrayHelper class for details.
29 public abstract class Array : ICloneable, IList, IStructuralComparable, IStructuralEquatable
31 // This ctor exists solely to prevent C# from generating a protected .ctor that violates the surface area. I really want this to be a
32 // "protected-and-internal" rather than "internal" but C# has no keyword for the former.
35 public static ReadOnlyCollection<T> AsReadOnly<T>(T[] array) {
37 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
39 Contract.Ensures(Contract.Result<ReadOnlyCollection<T>>() != null);
41 // T[] implements IList<T>.
42 return new ReadOnlyCollection<T>(array);
45 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
46 public static void Resize<T>(ref T[] array, int newSize) {
48 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.newSize, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
49 Contract.Ensures(Contract.ValueAtReturn(out array) != null);
50 Contract.Ensures(Contract.ValueAtReturn(out array).Length == newSize);
51 Contract.EndContractBlock();
55 array = new T[newSize];
59 if (larray.Length != newSize) {
60 T[] newArray = new T[newSize];
61 Array.Copy(larray, 0, newArray, 0, larray.Length > newSize? newSize : larray.Length);
66 // Create instance will create an array
67 [System.Security.SecuritySafeCritical] // auto-generated
68 public unsafe static Array CreateInstance(Type elementType, int length)
70 if ((object)elementType == null)
71 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.elementType);
73 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
74 Contract.Ensures(Contract.Result<Array>() != null);
75 Contract.Ensures(Contract.Result<Array>().Length == length);
76 Contract.Ensures(Contract.Result<Array>().Rank == 1);
77 Contract.EndContractBlock();
79 RuntimeType t = elementType.UnderlyingSystemType as RuntimeType;
81 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_MustBeType, ExceptionArgument.elementType);
82 return InternalCreate((void*)t.TypeHandle.Value,1,&length,null);
85 [System.Security.SecuritySafeCritical] // auto-generated
86 public unsafe static Array CreateInstance(Type elementType, int length1, int length2)
88 if ((object)elementType == null)
89 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.elementType);
91 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length1, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
93 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length2, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
94 Contract.Ensures(Contract.Result<Array>() != null);
95 Contract.Ensures(Contract.Result<Array>().Rank == 2);
96 Contract.Ensures(Contract.Result<Array>().GetLength(0) == length1);
97 Contract.Ensures(Contract.Result<Array>().GetLength(1) == length2);
99 RuntimeType t = elementType.UnderlyingSystemType as RuntimeType;
101 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_MustBeType, ExceptionArgument.elementType);
102 int* pLengths = stackalloc int[2];
103 pLengths[0] = length1;
104 pLengths[1] = length2;
105 return InternalCreate((void*)t.TypeHandle.Value,2,pLengths,null);
108 [System.Security.SecuritySafeCritical] // auto-generated
109 public unsafe static Array CreateInstance(Type elementType, int length1, int length2, int length3)
111 if ((object)elementType == null)
112 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.elementType);
114 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length1, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
116 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length2, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
118 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length3, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
119 Contract.Ensures(Contract.Result<Array>() != null);
120 Contract.Ensures(Contract.Result<Array>().Rank == 3);
121 Contract.Ensures(Contract.Result<Array>().GetLength(0) == length1);
122 Contract.Ensures(Contract.Result<Array>().GetLength(1) == length2);
123 Contract.Ensures(Contract.Result<Array>().GetLength(2) == length3);
125 RuntimeType t = elementType.UnderlyingSystemType as RuntimeType;
127 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_MustBeType, ExceptionArgument.elementType);
128 int* pLengths = stackalloc int[3];
129 pLengths[0] = length1;
130 pLengths[1] = length2;
131 pLengths[2] = length3;
132 return InternalCreate((void*)t.TypeHandle.Value,3,pLengths,null);
135 [System.Security.SecuritySafeCritical] // auto-generated
136 public unsafe static Array CreateInstance(Type elementType, params int[] lengths)
138 if ((object)elementType == null)
139 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.elementType);
141 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.lengths);
142 if (lengths.Length == 0)
143 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NeedAtLeast1Rank);
144 Contract.Ensures(Contract.Result<Array>() != null);
145 Contract.Ensures(Contract.Result<Array>().Rank == lengths.Length);
146 Contract.EndContractBlock();
148 RuntimeType t = elementType.UnderlyingSystemType as RuntimeType;
150 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_MustBeType, ExceptionArgument.elementType);
152 // Check to make sure the lenghts are all positive. Note that we check this here to give
153 // a good exception message if they are not; however we check this again inside the execution
154 // engine's low level allocation function after having made a copy of the array to prevent a
155 // malicious caller from mutating the array after this check.
156 for (int i = 0; i < lengths.Length; i++)
158 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.lengths, i, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
160 fixed (int* pLengths = lengths)
161 return InternalCreate((void*)t.TypeHandle.Value,lengths.Length,pLengths,null);
164 public static Array CreateInstance(Type elementType, params long[] lengths)
166 if( lengths == null) {
167 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.lengths);
169 if (lengths.Length == 0)
170 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NeedAtLeast1Rank);
171 Contract.Ensures(Contract.Result<Array>() != null);
172 Contract.Ensures(Contract.Result<Array>().Rank == lengths.Length);
173 Contract.EndContractBlock();
175 int[] intLengths = new int[lengths.Length];
177 for (int i = 0; i < lengths.Length; ++i)
179 long len = lengths[i];
180 if (len > Int32.MaxValue || len < Int32.MinValue)
181 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.len, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
182 intLengths[i] = (int) len;
185 return Array.CreateInstance(elementType, intLengths);
189 [System.Security.SecuritySafeCritical] // auto-generated
190 public unsafe static Array CreateInstance(Type elementType, int[] lengths,int[] lowerBounds)
192 if (elementType == null)
193 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.elementType);
195 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.lengths);
196 if (lowerBounds == null)
197 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.lowerBounds);
198 if (lengths.Length != lowerBounds.Length)
199 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RanksAndBounds);
200 if (lengths.Length == 0)
201 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NeedAtLeast1Rank);
202 Contract.Ensures(Contract.Result<Array>() != null);
203 Contract.Ensures(Contract.Result<Array>().Rank == lengths.Length);
204 Contract.EndContractBlock();
206 RuntimeType t = elementType.UnderlyingSystemType as RuntimeType;
208 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_MustBeType, ExceptionArgument.elementType);
210 // Check to make sure the lenghts are all positive. Note that we check this here to give
211 // a good exception message if they are not; however we check this again inside the execution
212 // engine's low level allocation function after having made a copy of the array to prevent a
213 // malicious caller from mutating the array after this check.
214 for (int i=0;i<lengths.Length;i++)
216 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.lengths, i, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
218 fixed (int* pLengths = lengths)
219 fixed(int* pLowerBounds = lowerBounds)
220 return InternalCreate((void*)t.TypeHandle.Value,lengths.Length,pLengths,pLowerBounds);
222 [System.Security.SecurityCritical] // auto-generated
223 [MethodImplAttribute(MethodImplOptions.InternalCall)]
224 private unsafe static extern Array InternalCreate(void* elementType,int rank,int *pLengths,int *pLowerBounds);
228 [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
230 internal static Array UnsafeCreateInstance(Type elementType, int length)
232 return CreateInstance(elementType, length);
237 [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
239 internal static Array UnsafeCreateInstance(Type elementType, int length1, int length2)
241 return CreateInstance(elementType, length1, length2);
246 [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
248 internal static Array UnsafeCreateInstance(Type elementType, params int[] lengths)
250 return CreateInstance(elementType, lengths);
255 [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
257 internal static Array UnsafeCreateInstance(Type elementType, int[] lengths, int[] lowerBounds)
259 return CreateInstance(elementType, lengths, lowerBounds);
262 // Copies length elements from sourceArray, starting at index 0, to
263 // destinationArray, starting at index 0.
265 [System.Security.SecuritySafeCritical] // auto-generated
266 [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
267 public static void Copy(Array sourceArray, Array destinationArray, int length)
269 if (sourceArray == null)
270 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.sourceArray);
271 if (destinationArray == null)
272 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.destinationArray);
274 Contract.Requires(sourceArray.Rank == destinationArray.Rank);
275 Contract.Requires(length >= 0);
276 Contract.Requires(length <= sourceArray.GetLowerBound(0) + sourceArray.Length);
277 Contract.Requires(length <= destinationArray.GetLowerBound(0) + destinationArray.Length);
279 Contract.EndContractBlock();
281 Copy(sourceArray, sourceArray.GetLowerBound(0), destinationArray, destinationArray.GetLowerBound(0), length, false);
284 // Copies length elements from sourceArray, starting at sourceIndex, to
285 // destinationArray, starting at destinationIndex.
287 [System.Security.SecuritySafeCritical] // auto-generated
288 [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
289 public static void Copy(Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length)
291 Copy(sourceArray, sourceIndex, destinationArray, destinationIndex, length, false);
294 // Reliability-wise, this method will either possibly corrupt your
295 // instance & might fail when called from within a CER, or if the
296 // reliable flag is true, it will either always succeed or always
297 // throw an exception with no side effects.
298 [System.Security.SecurityCritical] // auto-generated
299 [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
300 [MethodImplAttribute(MethodImplOptions.InternalCall)]
301 internal static extern void Copy(Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length, bool reliable);
303 // Provides a strong exception guarantee - either it succeeds, or
304 // it throws an exception with no side effects. The arrays must be
305 // compatible array types based on the array element type - this
306 // method does not support casting, boxing, or primitive widening.
307 // It will up-cast, assuming the array types are correct.
308 [System.Security.SecuritySafeCritical] // auto-generated
309 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
310 public static void ConstrainedCopy(Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length)
312 Copy(sourceArray, sourceIndex, destinationArray, destinationIndex, length, true);
315 [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
316 public static void Copy(Array sourceArray, Array destinationArray, long length)
318 if (length > Int32.MaxValue || length < Int32.MinValue)
319 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
321 Array.Copy(sourceArray, destinationArray, (int) length);
324 [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
325 public static void Copy(Array sourceArray, long sourceIndex, Array destinationArray, long destinationIndex, long length)
327 if (sourceIndex > Int32.MaxValue || sourceIndex < Int32.MinValue)
328 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.sourceIndex, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
329 if (destinationIndex > Int32.MaxValue || destinationIndex < Int32.MinValue)
330 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.destinationIndex, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
331 if (length > Int32.MaxValue || length < Int32.MinValue)
332 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
334 Array.Copy(sourceArray, (int) sourceIndex, destinationArray, (int) destinationIndex, (int) length);
338 // Sets length elements in array to 0 (or null for Object arrays), starting
341 [System.Security.SecuritySafeCritical] // auto-generated
342 [MethodImplAttribute(MethodImplOptions.InternalCall)]
343 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
344 public static extern void Clear(Array array, int index, int length);
346 // The various Get values...
347 [System.Security.SecuritySafeCritical] // auto-generated
348 public unsafe Object GetValue(params int[] indices)
351 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.indices);
352 if (Rank != indices.Length)
353 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankIndices);
354 Contract.EndContractBlock();
356 TypedReference elemref = new TypedReference();
357 fixed(int* pIndices = indices)
358 InternalGetReference(&elemref, indices.Length, pIndices);
359 return TypedReference.InternalToObject(&elemref);
362 [System.Security.SecuritySafeCritical] // auto-generated
363 public unsafe Object GetValue(int index)
366 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_Need1DArray);
367 Contract.EndContractBlock();
369 TypedReference elemref = new TypedReference();
370 InternalGetReference(&elemref, 1, &index);
371 return TypedReference.InternalToObject(&elemref);
374 [System.Security.SecuritySafeCritical] // auto-generated
375 public unsafe Object GetValue(int index1, int index2)
378 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_Need2DArray);
379 Contract.EndContractBlock();
381 int* pIndices = stackalloc int[2];
382 pIndices[0] = index1;
383 pIndices[1] = index2;
385 TypedReference elemref = new TypedReference();
386 InternalGetReference(&elemref, 2, pIndices);
387 return TypedReference.InternalToObject(&elemref);
390 [System.Security.SecuritySafeCritical] // auto-generated
391 public unsafe Object GetValue(int index1, int index2, int index3)
394 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_Need3DArray);
395 Contract.EndContractBlock();
397 int* pIndices = stackalloc int[3];
398 pIndices[0] = index1;
399 pIndices[1] = index2;
400 pIndices[2] = index3;
402 TypedReference elemref = new TypedReference();
403 InternalGetReference(&elemref, 3, pIndices);
404 return TypedReference.InternalToObject(&elemref);
408 public Object GetValue(long index)
410 if (index > Int32.MaxValue || index < Int32.MinValue)
411 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
412 Contract.EndContractBlock();
414 return this.GetValue((int) index);
418 public Object GetValue(long index1, long index2)
420 if (index1 > Int32.MaxValue || index1 < Int32.MinValue)
421 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index1, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
422 if (index2 > Int32.MaxValue || index2 < Int32.MinValue)
423 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index2, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
424 Contract.EndContractBlock();
426 return this.GetValue((int) index1, (int) index2);
430 public Object GetValue(long index1, long index2, long index3)
432 if (index1 > Int32.MaxValue || index1 < Int32.MinValue)
433 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index1, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
434 if (index2 > Int32.MaxValue || index2 < Int32.MinValue)
435 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index2, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
436 if (index3 > Int32.MaxValue || index3 < Int32.MinValue)
437 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index3, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
438 Contract.EndContractBlock();
440 return this.GetValue((int) index1, (int) index2, (int) index3);
444 public Object GetValue(params long[] indices)
447 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.indices);
448 if (Rank != indices.Length)
449 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankIndices);
450 Contract.EndContractBlock();
452 int[] intIndices = new int[indices.Length];
454 for (int i = 0; i < indices.Length; ++i)
456 long index = indices[i];
457 if (index > Int32.MaxValue || index < Int32.MinValue)
458 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
459 intIndices[i] = (int) index;
462 return this.GetValue(intIndices);
466 [System.Security.SecuritySafeCritical] // auto-generated
467 public unsafe void SetValue(Object value,int index)
470 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_Need1DArray);
471 Contract.EndContractBlock();
473 TypedReference elemref = new TypedReference();
474 InternalGetReference(&elemref, 1, &index);
475 InternalSetValue(&elemref,value);
478 [System.Security.SecuritySafeCritical] // auto-generated
479 public unsafe void SetValue(Object value,int index1, int index2)
482 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_Need2DArray);
483 Contract.EndContractBlock();
485 int* pIndices = stackalloc int[2];
486 pIndices[0] = index1;
487 pIndices[1] = index2;
489 TypedReference elemref = new TypedReference();
490 InternalGetReference(&elemref, 2, pIndices);
491 InternalSetValue(&elemref,value);
494 [System.Security.SecuritySafeCritical] // auto-generated
495 public unsafe void SetValue(Object value,int index1, int index2, int index3)
498 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_Need3DArray);
499 Contract.EndContractBlock();
501 int* pIndices = stackalloc int[3];
502 pIndices[0] = index1;
503 pIndices[1] = index2;
504 pIndices[2] = index3;
506 TypedReference elemref = new TypedReference();
507 InternalGetReference(&elemref, 3, pIndices);
508 InternalSetValue(&elemref,value);
511 [System.Security.SecuritySafeCritical] // auto-generated
512 public unsafe void SetValue(Object value,params int[] indices)
515 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.indices);
516 if (Rank != indices.Length)
517 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankIndices);
518 Contract.EndContractBlock();
520 TypedReference elemref = new TypedReference();
521 fixed(int* pIndices = indices)
522 InternalGetReference(&elemref, indices.Length, pIndices);
523 InternalSetValue(&elemref,value);
527 public void SetValue(Object value, long index)
529 if (index > Int32.MaxValue || index < Int32.MinValue)
530 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
531 Contract.EndContractBlock();
533 this.SetValue(value, (int) index);
537 public void SetValue(Object value, long index1, long index2)
539 if (index1 > Int32.MaxValue || index1 < Int32.MinValue)
540 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index1, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
541 if (index2 > Int32.MaxValue || index2 < Int32.MinValue)
542 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index2, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
543 Contract.EndContractBlock();
545 this.SetValue(value, (int) index1, (int) index2);
549 public void SetValue(Object value, long index1, long index2, long index3)
551 if (index1 > Int32.MaxValue || index1 < Int32.MinValue)
552 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index1, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
553 if (index2 > Int32.MaxValue || index2 < Int32.MinValue)
554 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index2, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
555 if (index3 > Int32.MaxValue || index3 < Int32.MinValue)
556 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index3, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
557 Contract.EndContractBlock();
559 this.SetValue(value, (int) index1, (int) index2, (int) index3);
563 public void SetValue(Object value, params long[] indices)
566 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.indices);
567 if (Rank != indices.Length)
568 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankIndices);
569 Contract.EndContractBlock();
571 int[] intIndices = new int[indices.Length];
573 for (int i = 0; i < indices.Length; ++i)
575 long index = indices[i];
576 if (index > Int32.MaxValue || index < Int32.MinValue)
577 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
578 intIndices[i] = (int) index;
581 this.SetValue(value, intIndices);
584 [System.Security.SecurityCritical] // auto-generated
585 [MethodImplAttribute(MethodImplOptions.InternalCall)]
586 // reference to TypedReference is banned, so have to pass result as pointer
587 private unsafe extern void InternalGetReference(void * elemRef, int rank, int * pIndices);
589 // Ideally, we would like to use TypedReference.SetValue instead. Unfortunately, TypedReference.SetValue
590 // always throws not-supported exception
591 [System.Security.SecurityCritical] // auto-generated
592 [MethodImplAttribute(MethodImplOptions.InternalCall)]
593 private unsafe extern static void InternalSetValue(void * target, Object value);
595 public extern int Length {
597 [System.Security.SecuritySafeCritical] // auto-generated
598 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
599 [MethodImpl(MethodImplOptions.InternalCall)]
603 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
604 private static int GetMedian(int low, int hi) {
605 // Note both may be negative, if we are dealing with arrays w/ negative lower bounds.
606 Contract.Requires(low <= hi);
607 Contract.Assert( hi - low >= 0, "Length overflow!");
608 return low + ((hi - low) >> 1);
611 // We impose limits on maximum array lenght in each dimension to allow efficient
612 // implementation of advanced range check elimination in future.
613 // Keep in sync with vm\gcscan.cpp and HashHelpers.MaxPrimeArrayLength.
614 // The constants are defined in this method: inline SIZE_T MaxArrayLength(SIZE_T componentSize) from gcscan
615 // We have different max sizes for arrays with elements of size 1 for backwards compatibility
616 internal const int MaxArrayLength = 0X7FEFFFFF;
617 internal const int MaxByteArrayLength = 0x7FFFFFC7;
620 public extern long LongLength {
622 [System.Security.SecuritySafeCritical] // auto-generated
623 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
624 [MethodImpl(MethodImplOptions.InternalCall)]
629 [System.Security.SecuritySafeCritical] // auto-generated
630 [MethodImplAttribute(MethodImplOptions.InternalCall)]
631 public extern int GetLength(int dimension);
635 public long GetLongLength(int dimension) {
636 //This method should throw an IndexOufOfRangeException for compat if dimension < 0 or >= Rank
637 return GetLength(dimension);
640 public extern int Rank {
642 [System.Security.SecuritySafeCritical] // auto-generated
643 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
644 [MethodImplAttribute(MethodImplOptions.InternalCall)]
648 [System.Security.SecuritySafeCritical] // auto-generated
650 [MethodImplAttribute(MethodImplOptions.InternalCall)]
651 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
652 public extern int GetUpperBound(int dimension);
654 [System.Security.SecuritySafeCritical] // auto-generated
656 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
657 [MethodImplAttribute(MethodImplOptions.InternalCall)]
658 public extern int GetLowerBound(int dimension);
660 [System.Security.SecurityCritical] // auto-generated
661 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
662 [MethodImplAttribute(MethodImplOptions.InternalCall)]
663 internal extern int GetDataPtrOffsetInternal();
665 // Number of elements in the Array.
666 int ICollection.Count
667 { get { return Length; } }
670 // Returns an object appropriate for synchronizing access to this
672 public Object SyncRoot
673 { get { return this; } }
675 // Is this Array read-only?
676 public bool IsReadOnly
677 { get { return false; } }
679 public bool IsFixedSize {
683 // Is this Array synchronized (i.e., thread-safe)? If you want a synchronized
684 // collection, you can use SyncRoot as an object to synchronize your
685 // collection with. You could also call GetSynchronized()
686 // to get a synchronized wrapper around the Array.
687 public bool IsSynchronized
688 { get { return false; } }
691 Object IList.this[int index] {
692 get { return GetValue(index); }
693 set { SetValue(value, index); }
696 int IList.Add(Object value)
698 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_FixedSizeCollection);
702 bool IList.Contains(Object value)
704 return Array.IndexOf(this, value) >= this.GetLowerBound(0);
709 Array.Clear(this, this.GetLowerBound(0), this.Length);
712 int IList.IndexOf(Object value)
714 return Array.IndexOf(this, value);
717 void IList.Insert(int index, Object value)
719 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_FixedSizeCollection);
722 void IList.Remove(Object value)
724 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_FixedSizeCollection);
727 void IList.RemoveAt(int index)
729 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_FixedSizeCollection);
732 // Make a new array which is a shallow copy of the original array.
734 public Object Clone()
736 return MemberwiseClone();
739 Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer) {
744 Array o = other as Array;
746 if (o == null || this.Length != o.Length)
748 ThrowHelper.ThrowArgumentException(ExceptionResource.ArgumentException_OtherNotArrayOfCorrectLength, ExceptionArgument.other);
754 while (i < o.Length && c == 0) {
755 object left = GetValue(i);
756 object right = o.GetValue(i);
758 c = comparer.Compare(left, right);
765 Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer) {
771 if (Object.ReferenceEquals(this, other)) {
775 Array o = other as Array;
777 if (o == null || o.Length != this.Length) {
782 while (i < o.Length) {
783 object left = GetValue(i);
784 object right = o.GetValue(i);
786 if (!comparer.Equals(left, right)) {
795 // From System.Web.Util.HashCodeCombiner
796 internal static int CombineHashCodes(int h1, int h2) {
797 return (((h1 << 5) + h1) ^ h2);
800 int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) {
801 if (comparer == null)
802 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.comparer);
803 Contract.EndContractBlock();
807 for (int i = (this.Length >= 8 ? this.Length - 8 : 0); i < this.Length; i++) {
808 ret = CombineHashCodes(ret, comparer.GetHashCode(GetValue(i)));
814 // Searches an array for a given element using a binary search algorithm.
815 // Elements of the array are compared to the search value using the
816 // IComparable interface, which must be implemented by all elements
817 // of the array and the given search value. This method assumes that the
818 // array is already sorted according to the IComparable interface;
819 // if this is not the case, the result will be incorrect.
821 // The method returns the index of the given value in the array. If the
822 // array does not contain the given value, the method returns a negative
823 // integer. The bitwise complement operator (~) can be applied to a
824 // negative result to produce the index of the first element (if any) that
825 // is larger than the given search value.
828 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
829 public static int BinarySearch(Array array, Object value) {
831 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
832 Contract.Ensures((Contract.Result<int>() >= array.GetLowerBound(0) && Contract.Result<int>() <= array.GetUpperBound(0)) || (Contract.Result<int>() < array.GetLowerBound(0) && ~Contract.Result<int>() <= array.GetUpperBound(0) + 1));
833 Contract.EndContractBlock();
834 int lb = array.GetLowerBound(0);
835 return BinarySearch(array, lb, array.Length, value, null);
838 // Searches a section of an array for a given element using a binary search
839 // algorithm. Elements of the array are compared to the search value using
840 // the IComparable interface, which must be implemented by all
841 // elements of the array and the given search value. This method assumes
842 // that the array is already sorted according to the IComparable
843 // interface; if this is not the case, the result will be incorrect.
845 // The method returns the index of the given value in the array. If the
846 // array does not contain the given value, the method returns a negative
847 // integer. The bitwise complement operator (~) can be applied to a
848 // negative result to produce the index of the first element (if any) that
849 // is larger than the given search value.
852 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
853 public static int BinarySearch(Array array, int index, int length, Object value) {
854 return BinarySearch(array, index, length, value, null);
857 // Searches an array for a given element using a binary search algorithm.
858 // Elements of the array are compared to the search value using the given
859 // IComparer interface. If comparer is null, elements of the
860 // array are compared to the search value using the IComparable
861 // interface, which in that case must be implemented by all elements of the
862 // array and the given search value. This method assumes that the array is
863 // already sorted; if this is not the case, the result will be incorrect.
865 // The method returns the index of the given value in the array. If the
866 // array does not contain the given value, the method returns a negative
867 // integer. The bitwise complement operator (~) can be applied to a
868 // negative result to produce the index of the first element (if any) that
869 // is larger than the given search value.
872 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
873 public static int BinarySearch(Array array, Object value, IComparer comparer) {
875 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
876 Contract.EndContractBlock();
877 int lb = array.GetLowerBound(0);
878 return BinarySearch(array, lb, array.Length, value, comparer);
881 // Searches a section of an array for a given element using a binary search
882 // algorithm. Elements of the array are compared to the search value using
883 // the given IComparer interface. If comparer is null,
884 // elements of the array are compared to the search value using the
885 // IComparable interface, which in that case must be implemented by
886 // all elements of the array and the given search value. This method
887 // assumes that the array is already sorted; if this is not the case, the
888 // result will be incorrect.
890 // The method returns the index of the given value in the array. If the
891 // array does not contain the given value, the method returns a negative
892 // integer. The bitwise complement operator (~) can be applied to a
893 // negative result to produce the index of the first element (if any) that
894 // is larger than the given search value.
897 [System.Security.SecuritySafeCritical] // auto-generated
898 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
899 public static int BinarySearch(Array array, int index, int length, Object value, IComparer comparer) {
901 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
902 Contract.EndContractBlock();
903 int lb = array.GetLowerBound(0);
905 ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
907 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
908 if (array.Length - (index - lb) < length)
909 ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
911 ThrowHelper.ThrowRankException(ExceptionResource.Rank_MultiDimNotSupported);
913 if (comparer == null) comparer = Comparer.Default;
914 if (comparer == Comparer.Default) {
916 bool r = TrySZBinarySearch(array, index, length, value, out retval);
922 int hi = index + length - 1;
923 Object[] objArray = array as Object[];
924 if(objArray != null) {
926 // i might overflow if lo and hi are both large positive numbers.
927 int i = GetMedian(lo, hi);
931 c = comparer.Compare(objArray[i], value);
933 catch (Exception e) {
934 ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e);
936 if (c == 0) return i;
947 int i = GetMedian(lo, hi);
951 c = comparer.Compare(array.GetValue(i), value);
953 catch (Exception e) {
954 ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e);
956 if (c == 0) return i;
968 [System.Security.SecurityCritical] // auto-generated
969 [MethodImplAttribute(MethodImplOptions.InternalCall)]
970 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
971 private static extern bool TrySZBinarySearch(Array sourceArray, int sourceIndex, int count, Object value, out int retVal);
974 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
975 public static int BinarySearch<T>(T[] array, T value) {
977 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
978 Contract.EndContractBlock();
979 return BinarySearch<T>(array, 0, array.Length, value, null);
983 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
984 public static int BinarySearch<T>(T[] array, T value, System.Collections.Generic.IComparer<T> comparer) {
986 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
987 Contract.EndContractBlock();
988 return BinarySearch<T>(array, 0, array.Length, value, comparer);
992 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
993 public static int BinarySearch<T>(T[] array, int index, int length, T value) {
994 return BinarySearch<T>(array, index, length, value, null);
998 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
999 public static int BinarySearch<T>(T[] array, int index, int length, T value, System.Collections.Generic.IComparer<T> comparer) {
1001 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1003 ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
1005 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
1007 if (array.Length - index < length)
1008 ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
1009 Contract.EndContractBlock();
1011 return ArraySortHelper<T>.Default.BinarySearch(array, index, length, value, comparer);
1014 public static TOutput[] ConvertAll<TInput, TOutput>(TInput[] array, Converter<TInput,TOutput> converter) {
1015 if( array == null) {
1016 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1019 if( converter == null) {
1020 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.converter);
1022 Contract.Ensures(Contract.Result<TOutput[]>() != null);
1023 Contract.Ensures(Contract.Result<TOutput[]>().Length == array.Length);
1024 Contract.EndContractBlock();
1026 TOutput[] newArray = new TOutput[array.Length];
1027 for( int i = 0; i< array.Length; i++) {
1028 newArray[i] = converter(array[i]);
1033 // CopyTo copies a collection into an Array, starting at a particular
1034 // index into the array.
1036 // This method is to support the ICollection interface, and calls
1037 // Array.Copy internally. If you aren't using ICollection explicitly,
1038 // call Array.Copy to avoid an extra indirection.
1041 public void CopyTo(Array array, int index)
1043 if (array != null && array.Rank != 1)
1044 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
1045 Contract.EndContractBlock();
1046 // Note: Array.Copy throws a RankException and we want a consistent ArgumentException for all the IList CopyTo methods.
1047 Array.Copy(this, GetLowerBound(0), array, index, Length);
1052 public void CopyTo(Array array, long index)
1054 if (index > Int32.MaxValue || index < Int32.MinValue)
1055 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
1056 Contract.EndContractBlock();
1058 this.CopyTo(array, (int) index);
1062 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
1063 public static T[] Empty<T>()
1065 Contract.Ensures(Contract.Result<T[]>() != null);
1066 Contract.Ensures(Contract.Result<T[]>().Length == 0);
1067 Contract.EndContractBlock();
1069 return EmptyArray<T>.Value;
1072 public static bool Exists<T>(T[] array, Predicate<T> match) {
1073 return Array.FindIndex(array, match) != -1;
1076 public static T Find<T>(T[] array, Predicate<T> match) {
1077 if( array == null) {
1078 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1081 if( match == null) {
1082 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
1084 Contract.EndContractBlock();
1086 for(int i = 0 ; i < array.Length; i++) {
1087 if(match(array[i])) {
1094 public static T[] FindAll<T>(T[] array, Predicate<T> match) {
1095 if( array == null) {
1096 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1099 if( match == null) {
1100 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
1102 Contract.EndContractBlock();
1104 List<T> list = new List<T>();
1105 for(int i = 0 ; i < array.Length; i++) {
1106 if(match(array[i])) {
1110 return list.ToArray();
1113 public static int FindIndex<T>(T[] array, Predicate<T> match) {
1115 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1117 Contract.Ensures(Contract.Result<int>() < array.Length);
1118 Contract.EndContractBlock();
1120 return FindIndex(array, 0, array.Length, match);
1123 public static int FindIndex<T>(T[] array, int startIndex, Predicate<T> match) {
1125 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1127 Contract.Ensures(Contract.Result<int>() < array.Length);
1128 Contract.EndContractBlock();
1130 return FindIndex(array, startIndex, array.Length - startIndex, match);
1133 public static int FindIndex<T>(T[] array, int startIndex, int count, Predicate<T> match) {
1135 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1138 if( startIndex < 0 || startIndex > array.Length ) {
1139 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
1142 if (count < 0 || startIndex > array.Length - count) {
1143 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count);
1146 if( match == null) {
1147 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
1149 Contract.Ensures(Contract.Result<int>() < array.Length);
1150 Contract.EndContractBlock();
1152 int endIndex = startIndex + count;
1153 for( int i = startIndex; i < endIndex; i++) {
1154 if( match(array[i])) return i;
1159 public static T FindLast<T>(T[] array, Predicate<T> match) {
1160 if( array == null) {
1161 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1164 if( match == null) {
1165 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
1167 Contract.EndContractBlock();
1169 for(int i = array.Length - 1 ; i >= 0; i--) {
1170 if(match(array[i])) {
1177 public static int FindLastIndex<T>(T[] array, Predicate<T> match) {
1178 if( array == null) {
1179 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1181 Contract.EndContractBlock();
1183 return FindLastIndex(array, array.Length - 1, array.Length, match);
1186 public static int FindLastIndex<T>(T[] array, int startIndex, Predicate<T> match) {
1187 if( array == null) {
1188 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1190 Contract.EndContractBlock();
1192 return FindLastIndex(array, startIndex, startIndex + 1, match);
1195 public static int FindLastIndex<T>(T[] array, int startIndex, int count, Predicate<T> match) {
1196 if( array == null) {
1197 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1200 if( match == null) {
1201 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
1203 Contract.EndContractBlock();
1205 if(array.Length == 0) {
1206 // Special case for 0 length List
1207 if( startIndex != -1) {
1208 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
1212 // Make sure we're not out of range
1213 if ( startIndex < 0 || startIndex >= array.Length) {
1214 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
1218 // 2nd have of this also catches when startIndex == MAXINT, so MAXINT - 0 + 1 == -1, which is < 0.
1219 if (count < 0 || startIndex - count + 1 < 0) {
1220 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count);
1223 int endIndex = startIndex - count;
1224 for( int i = startIndex; i > endIndex; i--) {
1225 if( match(array[i])) {
1232 public static void ForEach<T>(T[] array, Action<T> action) {
1233 if( array == null) {
1234 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1237 if( action == null) {
1238 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.action);
1240 Contract.EndContractBlock();
1242 for(int i = 0 ; i < array.Length; i++) {
1247 // GetEnumerator returns an IEnumerator over this Array.
1249 // Currently, only one dimensional arrays are supported.
1251 public IEnumerator GetEnumerator()
1253 int lowerBound = GetLowerBound(0);
1254 if (Rank == 1 && lowerBound == 0)
1255 return new SZArrayEnumerator(this);
1257 return new ArrayEnumerator(this, lowerBound, Length);
1260 // Returns the index of the first occurrence of a given value in an array.
1261 // The array is searched forwards, and the elements of the array are
1262 // compared to the given value using the Object.Equals method.
1264 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
1265 public static int IndexOf(Array array, Object value) {
1267 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1268 Contract.Ensures(Contract.Result<int>() < array.GetLowerBound(0) + array.Length);
1269 Contract.EndContractBlock();
1270 int lb = array.GetLowerBound(0);
1271 return IndexOf(array, value, lb, array.Length);
1274 // Returns the index of the first occurrence of a given value in a range of
1275 // an array. The array is searched forwards, starting at index
1276 // startIndex and ending at the last element of the array. The
1277 // elements of the array are compared to the given value using the
1278 // Object.Equals method.
1280 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
1281 public static int IndexOf(Array array, Object value, int startIndex) {
1283 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1284 Contract.Ensures(Contract.Result<int>() < array.GetLowerBound(0) + array.Length);
1285 Contract.EndContractBlock();
1286 int lb = array.GetLowerBound(0);
1287 return IndexOf(array, value, startIndex, array.Length - startIndex + lb);
1290 // Returns the index of the first occurrence of a given value in a range of
1291 // an array. The array is searched forwards, starting at index
1292 // startIndex and upto count elements. The
1293 // elements of the array are compared to the given value using the
1294 // Object.Equals method.
1296 [System.Security.SecuritySafeCritical] // auto-generated
1297 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
1298 public static int IndexOf(Array array, Object value, int startIndex, int count) {
1300 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1301 if (array.Rank != 1)
1302 ThrowHelper.ThrowRankException(ExceptionResource.Rank_MultiDimNotSupported);
1303 Contract.Ensures(Contract.Result<int>() < array.GetLowerBound(0) + array.Length);
1304 Contract.EndContractBlock();
1306 int lb = array.GetLowerBound(0);
1307 if (startIndex < lb || startIndex > array.Length + lb)
1308 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
1309 if (count < 0 || count > array.Length - startIndex + lb)
1310 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count);
1312 // Try calling a quick native method to handle primitive types.
1314 bool r = TrySZIndexOf(array, startIndex, count, value, out retVal);
1318 Object[] objArray = array as Object[];
1319 int endIndex = startIndex + count;
1320 if (objArray != null) {
1321 if (value == null) {
1322 for (int i = startIndex; i < endIndex; i++) {
1323 if (objArray[i] == null) return i;
1327 for (int i = startIndex; i < endIndex; i++) {
1328 Object obj = objArray[i];
1329 if (obj != null && obj.Equals(value)) return i;
1334 for (int i = startIndex; i < endIndex; i++) {
1335 Object obj = array.GetValue(i);
1337 if(value == null) return i;
1340 if( obj.Equals(value)) return i;
1344 // Return one less than the lower bound of the array. This way,
1345 // for arrays with a lower bound of -1 we will not return -1 when the
1346 // item was not found. And for SZArrays (the vast majority), -1 still
1352 public static int IndexOf<T>(T[] array, T value) {
1354 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1356 Contract.Ensures((Contract.Result<int>() < 0) ||
1357 (Contract.Result<int>() >= 0 && Contract.Result<int>() < array.Length && EqualityComparer<T>.Default.Equals(value, array[Contract.Result<int>()])));
1358 Contract.EndContractBlock();
1360 return IndexOf(array, value, 0, array.Length);
1363 public static int IndexOf<T>(T[] array, T value, int startIndex) {
1365 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1367 Contract.Ensures(Contract.Result<int>() < array.Length);
1368 Contract.EndContractBlock();
1370 return IndexOf(array, value, startIndex, array.Length - startIndex);
1373 public static int IndexOf<T>(T[] array, T value, int startIndex, int count) {
1375 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1378 if (startIndex < 0 || startIndex > array.Length ) {
1379 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
1382 if (count < 0 || count > array.Length - startIndex) {
1383 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count);
1385 Contract.Ensures(Contract.Result<int>() < array.Length);
1386 Contract.EndContractBlock();
1388 return EqualityComparer<T>.Default.IndexOf(array, value, startIndex, count);
1391 [System.Security.SecurityCritical] // auto-generated
1392 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1393 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
1394 private static extern bool TrySZIndexOf(Array sourceArray, int sourceIndex, int count, Object value, out int retVal);
1397 // Returns the index of the last occurrence of a given value in an array.
1398 // The array is searched backwards, and the elements of the array are
1399 // compared to the given value using the Object.Equals method.
1401 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
1402 public static int LastIndexOf(Array array, Object value) {
1404 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1405 Contract.Ensures(Contract.Result<int>() < array.GetLowerBound(0) + array.Length);
1406 Contract.EndContractBlock();
1407 int lb = array.GetLowerBound(0);
1408 return LastIndexOf(array, value, array.Length - 1 + lb, array.Length);
1411 // Returns the index of the last occurrence of a given value in a range of
1412 // an array. The array is searched backwards, starting at index
1413 // startIndex and ending at index 0. The elements of the array are
1414 // compared to the given value using the Object.Equals method.
1416 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
1417 public static int LastIndexOf(Array array, Object value, int startIndex) {
1419 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1420 Contract.Ensures(Contract.Result<int>() < array.GetLowerBound(0) + array.Length);
1421 Contract.EndContractBlock();
1422 int lb = array.GetLowerBound(0);
1423 return LastIndexOf(array, value, startIndex, startIndex + 1 - lb);
1426 // Returns the index of the last occurrence of a given value in a range of
1427 // an array. The array is searched backwards, starting at index
1428 // startIndex and counting uptocount elements. The elements of
1429 // the array are compared to the given value using the Object.Equals
1432 [System.Security.SecuritySafeCritical] // auto-generated
1433 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
1434 public static int LastIndexOf(Array array, Object value, int startIndex, int count) {
1436 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1437 Contract.Ensures(Contract.Result<int>() < array.GetLowerBound(0) + array.Length);
1438 Contract.EndContractBlock();
1439 int lb = array.GetLowerBound(0);
1440 if (array.Length == 0) {
1444 if (startIndex < lb || startIndex >= array.Length + lb)
1445 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
1447 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count);
1448 if (count > startIndex - lb + 1)
1449 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.endIndex, ExceptionResource.ArgumentOutOfRange_EndIndexStartIndex);
1450 if (array.Rank != 1)
1451 ThrowHelper.ThrowRankException(ExceptionResource.Rank_MultiDimNotSupported);
1453 // Try calling a quick native method to handle primitive types.
1455 bool r = TrySZLastIndexOf(array, startIndex, count, value, out retVal);
1459 Object[] objArray = array as Object[];
1460 int endIndex = startIndex - count + 1;
1461 if (objArray!=null) {
1462 if (value == null) {
1463 for (int i = startIndex; i >= endIndex; i--) {
1464 if (objArray[i] == null) return i;
1468 for (int i = startIndex; i >= endIndex; i--) {
1469 Object obj = objArray[i];
1470 if (obj != null && obj.Equals(value)) return i;
1475 for (int i = startIndex; i >= endIndex; i--) {
1476 Object obj = array.GetValue(i);
1478 if(value == null) return i;
1481 if( obj.Equals(value)) return i;
1485 return lb-1; // Return lb-1 for arrays with negative lower bounds.
1488 public static int LastIndexOf<T>(T[] array, T value) {
1490 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1492 Contract.Ensures(Contract.Result<int>() < array.Length);
1493 Contract.EndContractBlock();
1495 return LastIndexOf(array, value, array.Length - 1, array.Length);
1498 public static int LastIndexOf<T>(T[] array, T value, int startIndex) {
1500 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1502 Contract.Ensures(Contract.Result<int>() < array.Length);
1503 Contract.EndContractBlock();
1504 // if array is empty and startIndex is 0, we need to pass 0 as count
1505 return LastIndexOf(array, value, startIndex, (array.Length == 0)? 0 : (startIndex + 1));
1508 public static int LastIndexOf<T>(T[] array, T value, int startIndex, int count) {
1510 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1512 Contract.Ensures(Contract.Result<int>() < array.Length);
1513 Contract.EndContractBlock();
1515 if(array.Length == 0) {
1517 // Special case for 0 length List
1518 // accept -1 and 0 as valid startIndex for compablility reason.
1520 if( startIndex != -1 && startIndex != 0) {
1521 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
1524 // only 0 is a valid value for count if array is empty
1526 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count);
1531 // Make sure we're not out of range
1532 if ( startIndex < 0 || startIndex >= array.Length) {
1533 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
1536 // 2nd have of this also catches when startIndex == MAXINT, so MAXINT - 0 + 1 == -1, which is < 0.
1537 if (count < 0 || startIndex - count + 1 < 0) {
1538 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count);
1541 return EqualityComparer<T>.Default.LastIndexOf(array, value, startIndex, count);
1544 [System.Security.SecurityCritical] // auto-generated
1545 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1546 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
1547 private static extern bool TrySZLastIndexOf(Array sourceArray, int sourceIndex, int count, Object value, out int retVal);
1550 // Reverses all elements of the given array. Following a call to this
1551 // method, an element previously located at index i will now be
1552 // located at index length - i - 1, where length is the
1553 // length of the array.
1555 [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
1556 public static void Reverse(Array array) {
1558 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1559 Contract.EndContractBlock();
1560 Reverse(array, array.GetLowerBound(0), array.Length);
1563 // Reverses the elements in a range of an array. Following a call to this
1564 // method, an element in the range given by index and count
1565 // which was previously located at index i will now be located at
1566 // index index + (index + count - i - 1).
1567 // Reliability note: This may fail because it may have to box objects.
1569 [System.Security.SecuritySafeCritical] // auto-generated
1570 [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
1571 public static void Reverse(Array array, int index, int length) {
1573 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1574 int lowerBound = array.GetLowerBound(0);
1575 if (index < lowerBound)
1576 ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
1578 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
1580 if (array.Length - (index - lowerBound) < length)
1581 ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
1582 if (array.Rank != 1)
1583 ThrowHelper.ThrowRankException(ExceptionResource.Rank_MultiDimNotSupported);
1584 Contract.EndContractBlock();
1586 bool r = TrySZReverse(array, index, length);
1591 int j = index + length - 1;
1592 Object[] objArray = array as Object[];
1593 if (objArray!=null) {
1595 Object temp = objArray[i];
1596 objArray[i] = objArray[j];
1604 Object temp = array.GetValue(i);
1605 array.SetValue(array.GetValue(j), i);
1606 array.SetValue(temp, j);
1613 [System.Security.SecurityCritical] // auto-generated
1614 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1615 [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
1616 private static extern bool TrySZReverse(Array array, int index, int count);
1618 [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
1619 public static void Reverse<T>(T[] array)
1622 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1623 Contract.EndContractBlock();
1624 Reverse(array, 0, array.Length);
1627 [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
1628 public static void Reverse<T>(T[] array, int index, int length)
1631 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1633 ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
1635 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
1636 if (array.Length - index < length)
1637 ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
1638 Contract.EndContractBlock();
1641 int j = index + length - 1;
1645 array[i] = array[j];
1652 // Sorts the elements of an array. The sort compares the elements to each
1653 // other using the IComparable interface, which must be implemented
1654 // by all elements of the array.
1656 [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
1657 public static void Sort(Array array) {
1659 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1660 Contract.EndContractBlock();
1661 Sort(array, null, array.GetLowerBound(0), array.Length, null);
1664 // Sorts the elements of two arrays based on the keys in the first array.
1665 // Elements in the keys array specify the sort keys for
1666 // corresponding elements in the items array. The sort compares the
1667 // keys to each other using the IComparable interface, which must be
1668 // implemented by all elements of the keys array.
1670 [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
1671 public static void Sort(Array keys, Array items) {
1673 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys);
1674 Contract.EndContractBlock();
1675 Sort(keys, items, keys.GetLowerBound(0), keys.Length, null);
1678 // Sorts the elements in a section of an array. The sort compares the
1679 // elements to each other using the IComparable interface, which
1680 // must be implemented by all elements in the given section of the array.
1682 [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
1683 public static void Sort(Array array, int index, int length) {
1684 Sort(array, null, index, length, null);
1687 // Sorts the elements in a section of two arrays based on the keys in the
1688 // first array. Elements in the keys array specify the sort keys for
1689 // corresponding elements in the items array. The sort compares the
1690 // keys to each other using the IComparable interface, which must be
1691 // implemented by all elements of the keys array.
1693 [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
1694 public static void Sort(Array keys, Array items, int index, int length) {
1695 Sort(keys, items, index, length, null);
1698 // Sorts the elements of an array. The sort compares the elements to each
1699 // other using the given IComparer interface. If comparer is
1700 // null, the elements are compared to each other using the
1701 // IComparable interface, which in that case must be implemented by
1702 // all elements of the array.
1704 [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
1705 public static void Sort(Array array, IComparer comparer) {
1707 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1708 Contract.EndContractBlock();
1709 Sort(array, null, array.GetLowerBound(0), array.Length, comparer);
1712 // Sorts the elements of two arrays based on the keys in the first array.
1713 // Elements in the keys array specify the sort keys for
1714 // corresponding elements in the items array. The sort compares the
1715 // keys to each other using the given IComparer interface. If
1716 // comparer is null, the elements are compared to each other using
1717 // the IComparable interface, which in that case must be implemented
1718 // by all elements of the keys array.
1720 [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
1721 public static void Sort(Array keys, Array items, IComparer comparer) {
1723 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys);
1724 Contract.EndContractBlock();
1725 Sort(keys, items, keys.GetLowerBound(0), keys.Length, comparer);
1728 // Sorts the elements in a section of an array. The sort compares the
1729 // elements to each other using the given IComparer interface. If
1730 // comparer is null, the elements are compared to each other using
1731 // the IComparable interface, which in that case must be implemented
1732 // by all elements in the given section of the array.
1734 [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
1735 public static void Sort(Array array, int index, int length, IComparer comparer) {
1736 Sort(array, null, index, length, comparer);
1739 // Sorts the elements in a section of two arrays based on the keys in the
1740 // first array. Elements in the keys array specify the sort keys for
1741 // corresponding elements in the items array. The sort compares the
1742 // keys to each other using the given IComparer interface. If
1743 // comparer is null, the elements are compared to each other using
1744 // the IComparable interface, which in that case must be implemented
1745 // by all elements of the given section of the keys array.
1747 [System.Security.SecuritySafeCritical] // auto-generated
1748 [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
1749 public static void Sort(Array keys, Array items, int index, int length, IComparer comparer) {
1751 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys);
1752 if (keys.Rank != 1 || (items != null && items.Rank != 1))
1753 ThrowHelper.ThrowRankException(ExceptionResource.Rank_MultiDimNotSupported);
1754 int keysLowerBound = keys.GetLowerBound(0);
1755 if (items != null && keysLowerBound != items.GetLowerBound(0))
1756 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_LowerBoundsMustMatch);
1757 if (index < keysLowerBound)
1758 ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
1760 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
1762 if (keys.Length - (index - keysLowerBound) < length || (items != null && (index - keysLowerBound) > items.Length - length))
1763 ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
1765 Contract.EndContractBlock();
1768 if (comparer == Comparer.Default || comparer == null) {
1769 bool r = TrySZSort(keys, items, index, index + length - 1);
1774 Object[] objKeys = keys as Object[];
1775 Object[] objItems = null;
1776 if (objKeys != null)
1777 objItems = items as Object[];
1778 if (objKeys != null && (items==null || objItems != null)) {
1779 SorterObjectArray sorter = new SorterObjectArray(objKeys, objItems, comparer);
1780 sorter.Sort(index, length);
1783 SorterGenericArray sorter = new SorterGenericArray(keys, items, comparer);
1784 sorter.Sort(index, length);
1789 [System.Security.SecurityCritical] // auto-generated
1790 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1791 [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
1792 private static extern bool TrySZSort(Array keys, Array items, int left, int right);
1794 [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
1795 public static void Sort<T>(T[] array) {
1797 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1798 Contract.EndContractBlock();
1799 Sort<T>(array, 0, array.Length, null);
1802 [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
1803 public static void Sort<TKey, TValue>(TKey[] keys, TValue[] items) {
1805 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys);
1806 Contract.EndContractBlock();
1807 Sort<TKey, TValue>(keys, items, 0, keys.Length, null);
1810 [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
1811 public static void Sort<T>(T[] array, int index, int length) {
1812 Sort<T>(array, index, length, null);
1815 [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
1816 public static void Sort<TKey, TValue>(TKey[] keys, TValue[] items, int index, int length) {
1817 Sort<TKey, TValue>(keys, items, index, length, null);
1820 [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
1821 public static void Sort<T>(T[] array, System.Collections.Generic.IComparer<T> comparer) {
1823 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1824 Contract.EndContractBlock();
1825 Sort<T>(array, 0, array.Length, comparer);
1828 [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
1829 public static void Sort<TKey, TValue>(TKey[] keys, TValue[] items, System.Collections.Generic.IComparer<TKey> comparer) {
1831 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys);
1832 Contract.EndContractBlock();
1833 Sort<TKey, TValue>(keys, items, 0, keys.Length, comparer);
1836 [System.Security.SecuritySafeCritical] // auto-generated
1837 [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
1838 public static void Sort<T>(T[] array, int index, int length, System.Collections.Generic.IComparer<T> comparer) {
1840 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1842 ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
1844 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
1845 if (array.Length - index < length)
1846 ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
1847 Contract.EndContractBlock();
1850 if ( comparer == null || comparer == Comparer<T>.Default ) {
1851 if(TrySZSort(array, null, index, index + length - 1)) {
1856 ArraySortHelper<T>.Default.Sort(array, index, length, comparer);
1860 [System.Security.SecuritySafeCritical] // auto-generated
1861 [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
1862 public static void Sort<TKey, TValue>(TKey[] keys, TValue[] items, int index, int length, System.Collections.Generic.IComparer<TKey> comparer) {
1864 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys);
1866 ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
1868 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
1869 if (keys.Length - index < length || (items != null && index > items.Length - length))
1870 ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
1871 Contract.EndContractBlock();
1874 if ( comparer == null || comparer == Comparer<TKey>.Default ) {
1875 if(TrySZSort(keys, items, index, index + length - 1)) {
1882 Sort<TKey>(keys, index, length, comparer);
1886 ArraySortHelper<TKey, TValue>.Default.Sort(keys, items, index, length, comparer);
1890 public static void Sort<T>(T[] array, Comparison<T> comparison) {
1891 if( array == null) {
1892 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1895 if( comparison == null) {
1896 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.comparison);
1898 Contract.EndContractBlock();
1900 IComparer<T> comparer = Comparer<T>.Create(comparison);
1901 Array.Sort(array, comparer);
1904 public static bool TrueForAll<T>(T[] array, Predicate<T> match) {
1905 if( array == null) {
1906 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
1909 if( match == null) {
1910 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
1912 Contract.EndContractBlock();
1914 for(int i = 0 ; i < array.Length; i++) {
1915 if( !match(array[i])) {
1923 // Private value type used by the Sort methods.
1924 private struct SorterObjectArray
1926 private Object[] keys;
1927 private Object[] items;
1928 private IComparer comparer;
1930 internal SorterObjectArray(Object[] keys, Object[] items, IComparer comparer) {
1931 if (comparer == null) comparer = Comparer.Default;
1934 this.comparer = comparer;
1937 internal void SwapIfGreaterWithItems(int a, int b)
1941 if (comparer.Compare(keys[a], keys[b]) > 0)
1943 Object temp = keys[a];
1948 Object item = items[a];
1949 items[a] = items[b];
1956 private void Swap(int i, int j)
1964 Object item = items[i];
1965 items[i] = items[j];
1970 internal void Sort(int left, int length)
1973 // Since QuickSort and IntrospectiveSort produce different sorting sequence for equal keys the upgrade
1974 // to IntrospectiveSort was quirked. However since the phone builds always shipped with the new sort aka
1975 // IntrospectiveSort and we would want to continue using this sort moving forward CoreCLR always uses the new sort.
1977 IntrospectiveSort(left, length);
1979 if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5)
1981 IntrospectiveSort(left, length);
1985 DepthLimitedQuickSort(left, length + left - 1, IntrospectiveSortUtilities.QuickSortDepthThreshold);
1990 #if !FEATURE_CORECLR
1991 private void DepthLimitedQuickSort(int left, int right, int depthLimit)
1993 // Can use the much faster jit helpers for array access.
1996 if (depthLimit == 0)
1998 // Add a try block here to detect IComparers (or their
1999 // underlying IComparables, etc) that are bogus.
2002 Heapsort(left, right);
2005 catch (IndexOutOfRangeException)
2007 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_BogusIComparer, ExceptionArgument.comparer);
2011 ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e);
2018 // pre-sort the low, middle (pivot), and high values in place.
2019 // this improves performance in the face of already sorted data, or
2020 // data that is made up of multiple sorted runs appended together.
2021 int middle = GetMedian(i, j);
2023 // Add a try block here to detect IComparers (or their
2024 // underlying IComparables, etc) that are bogus.
2027 SwapIfGreaterWithItems(i, middle); // swap the low with the mid point
2028 SwapIfGreaterWithItems(i, j); // swap the low with the high
2029 SwapIfGreaterWithItems(middle, j); // swap the middle with the high
2033 ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e);
2035 Object x = keys[middle];
2038 // Add a try block here to detect IComparers (or their
2039 // underlying IComparables, etc) that are bogus.
2042 while (comparer.Compare(keys[i], x) < 0) i++;
2043 while (comparer.Compare(x, keys[j]) < 0) j--;
2045 catch (IndexOutOfRangeException)
2047 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_BogusIComparer, ExceptionArgument.comparer);
2051 ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e);
2053 Contract.Assert(i >= left && j <= right, "(i>=left && j<=right) Sort failed - Is your IComparer bogus?");
2057 Object key = keys[i];
2062 Object item = items[i];
2063 items[i] = items[j];
2071 // The next iteration of the while loop is to "recursively" sort the larger half of the array and the
2072 // following calls recursively sort the smaller half. So we subtract one from depthLimit here so
2073 // both sorts see the new value.
2076 if (j - left <= right - i)
2078 if (left < j) DepthLimitedQuickSort(left, j, depthLimit);
2083 if (i < right) DepthLimitedQuickSort(i, right, depthLimit);
2086 } while (left < right);
2090 private void IntrospectiveSort(int left, int length)
2097 IntroSort(left, length + left - 1, 2 * IntrospectiveSortUtilities.FloorLog2(keys.Length));
2099 catch (IndexOutOfRangeException)
2101 IntrospectiveSortUtilities.ThrowOrIgnoreBadComparer(comparer);
2105 ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e);
2109 private void IntroSort(int lo, int hi, int depthLimit)
2113 int partitionSize = hi - lo + 1;
2114 if (partitionSize <= IntrospectiveSortUtilities.IntrosortSizeThreshold)
2116 if (partitionSize == 1)
2120 if (partitionSize == 2)
2122 SwapIfGreaterWithItems(lo, hi);
2125 if (partitionSize == 3)
2127 SwapIfGreaterWithItems(lo, hi-1);
2128 SwapIfGreaterWithItems(lo, hi);
2129 SwapIfGreaterWithItems(hi-1, hi);
2133 InsertionSort(lo, hi);
2137 if (depthLimit == 0)
2144 int p = PickPivotAndPartition(lo, hi);
2145 IntroSort(p + 1, hi, depthLimit);
2150 private int PickPivotAndPartition(int lo, int hi)
2152 // Compute median-of-three. But also partition them, since we've done the comparison.
2153 int mid = lo + (hi - lo) / 2;
2154 // Sort lo, mid and hi appropriately, then pick mid as the pivot.
2155 SwapIfGreaterWithItems(lo, mid);
2156 SwapIfGreaterWithItems(lo, hi);
2157 SwapIfGreaterWithItems(mid, hi);
2159 Object pivot = keys[mid];
2161 int left = lo, right = hi - 1; // We already partitioned lo and hi and put the pivot in hi - 1. And we pre-increment & decrement below.
2163 while (left < right)
2165 while (comparer.Compare(keys[++left], pivot) < 0) ;
2166 while (comparer.Compare(pivot, keys[--right]) < 0) ;
2174 // Put pivot in the right location.
2175 Swap(left, (hi - 1));
2179 private void Heapsort(int lo, int hi)
2181 int n = hi - lo + 1;
2182 for (int i = n / 2; i >= 1; i = i - 1)
2186 for (int i = n; i > 1; i = i - 1)
2188 Swap(lo, lo + i - 1);
2190 DownHeap(1, i - 1, lo);
2194 private void DownHeap(int i, int n, int lo)
2196 Object d = keys[lo + i - 1];
2197 Object dt = (items != null) ? items[lo + i - 1] : null;
2202 if (child < n && comparer.Compare(keys[lo + child - 1], keys[lo + child]) < 0)
2206 if (!(comparer.Compare(d, keys[lo + child - 1]) < 0))
2208 keys[lo + i - 1] = keys[lo + child - 1];
2210 items[lo + i - 1] = items[lo + child - 1];
2213 keys[lo + i - 1] = d;
2215 items[lo + i - 1] = dt;
2218 private void InsertionSort(int lo, int hi)
2222 for (i = lo; i < hi; i++)
2226 ti = (items != null) ? items[i + 1] : null;
2227 while (j >= lo && comparer.Compare(t, keys[j]) < 0)
2229 keys[j + 1] = keys[j];
2231 items[j + 1] = items[j];
2241 // Private value used by the Sort methods for instances of Array.
2242 // This is slower than the one for Object[], since we can't use the JIT helpers
2243 // to access the elements. We must use GetValue & SetValue.
2244 private struct SorterGenericArray
2247 private Array items;
2248 private IComparer comparer;
2250 internal SorterGenericArray(Array keys, Array items, IComparer comparer)
2252 if (comparer == null) comparer = Comparer.Default;
2255 this.comparer = comparer;
2258 internal void SwapIfGreaterWithItems(int a, int b)
2262 if (comparer.Compare(keys.GetValue(a), keys.GetValue(b)) > 0)
2264 Object key = keys.GetValue(a);
2265 keys.SetValue(keys.GetValue(b), a);
2266 keys.SetValue(key, b);
2269 Object item = items.GetValue(a);
2270 items.SetValue(items.GetValue(b), a);
2271 items.SetValue(item, b);
2277 private void Swap(int i, int j)
2279 Object t1 = keys.GetValue(i);
2280 keys.SetValue(keys.GetValue(j), i);
2281 keys.SetValue(t1, j);
2285 Object t2 = items.GetValue(i);
2286 items.SetValue(items.GetValue(j), i);
2287 items.SetValue(t2, j);
2291 internal void Sort(int left, int length)
2294 // Since QuickSort and IntrospectiveSort produce different sorting sequence for equal keys the upgrade
2295 // to IntrospectiveSort was quirked. However since the phone builds always shipped with the new sort aka
2296 // IntrospectiveSort and we would want to continue using this sort moving forward CoreCLR always uses the new sort.
2298 IntrospectiveSort(left, length);
2300 if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5)
2302 IntrospectiveSort(left, length);
2306 DepthLimitedQuickSort(left, length + left - 1, IntrospectiveSortUtilities.QuickSortDepthThreshold);
2311 #if !FEATURE_CORECLR
2312 private void DepthLimitedQuickSort(int left, int right, int depthLimit)
2314 // Must use slow Array accessors (GetValue & SetValue)
2317 if (depthLimit == 0)
2319 // Add a try block here to detect IComparers (or their
2320 // underlying IComparables, etc) that are bogus.
2323 Heapsort(left, right);
2326 catch (IndexOutOfRangeException)
2328 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_BogusIComparer, ExceptionArgument.comparer);
2332 ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e);
2339 // pre-sort the low, middle (pivot), and high values in place.
2340 // this improves performance in the face of already sorted data, or
2341 // data that is made up of multiple sorted runs appended together.
2342 int middle = GetMedian(i, j);
2345 SwapIfGreaterWithItems(i, middle); // swap the low with the mid point
2346 SwapIfGreaterWithItems(i, j); // swap the low with the high
2347 SwapIfGreaterWithItems(middle, j); // swap the middle with the high
2351 ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e);
2354 Object x = keys.GetValue(middle);
2357 // Add a try block here to detect IComparers (or their
2358 // underlying IComparables, etc) that are bogus.
2361 while (comparer.Compare(keys.GetValue(i), x) < 0) i++;
2362 while (comparer.Compare(x, keys.GetValue(j)) < 0) j--;
2364 catch (IndexOutOfRangeException)
2366 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_BogusIComparer, ExceptionArgument.comparer);
2370 ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e);
2372 Contract.Assert(i >= left && j <= right, "(i>=left && j<=right) Sort failed - Is your IComparer bogus?");
2376 Object key = keys.GetValue(i);
2377 keys.SetValue(keys.GetValue(j), i);
2378 keys.SetValue(key, j);
2381 Object item = items.GetValue(i);
2382 items.SetValue(items.GetValue(j), i);
2383 items.SetValue(item, j);
2386 if (i != Int32.MaxValue) ++i;
2387 if (j != Int32.MinValue) --j;
2390 // The next iteration of the while loop is to "recursively" sort the larger half of the array and the
2391 // following calls recursively sort the smaller half. So we subtract one from depthLimit here so
2392 // both sorts see the new value.
2395 if (j - left <= right - i)
2397 if (left < j) DepthLimitedQuickSort(left, j, depthLimit);
2402 if (i < right) DepthLimitedQuickSort(i, right, depthLimit);
2405 } while (left < right);
2409 private void IntrospectiveSort(int left, int length)
2416 IntroSort(left, length + left - 1, 2 * IntrospectiveSortUtilities.FloorLog2(keys.Length));
2418 catch (IndexOutOfRangeException)
2420 IntrospectiveSortUtilities.ThrowOrIgnoreBadComparer(comparer);
2424 ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e);
2428 private void IntroSort(int lo, int hi, int depthLimit)
2432 int partitionSize = hi - lo + 1;
2433 if (partitionSize <= IntrospectiveSortUtilities.IntrosortSizeThreshold)
2435 if (partitionSize == 1)
2439 if (partitionSize == 2)
2441 SwapIfGreaterWithItems(lo, hi);
2444 if (partitionSize == 3)
2446 SwapIfGreaterWithItems(lo, hi-1);
2447 SwapIfGreaterWithItems(lo, hi);
2448 SwapIfGreaterWithItems(hi-1, hi);
2452 InsertionSort(lo, hi);
2456 if (depthLimit == 0)
2463 int p = PickPivotAndPartition(lo, hi);
2464 IntroSort(p + 1, hi, depthLimit);
2469 private int PickPivotAndPartition(int lo, int hi)
2471 // Compute median-of-three. But also partition them, since we've done the comparison.
2472 int mid = lo + (hi - lo) / 2;
2474 SwapIfGreaterWithItems(lo, mid);
2475 SwapIfGreaterWithItems(lo, hi);
2476 SwapIfGreaterWithItems(mid, hi);
2478 Object pivot = keys.GetValue(mid);
2480 int left = lo, right = hi - 1; // We already partitioned lo and hi and put the pivot in hi - 1. And we pre-increment & decrement below.
2482 while (left < right)
2484 while (comparer.Compare(keys.GetValue(++left), pivot) < 0) ;
2485 while (comparer.Compare(pivot, keys.GetValue(--right)) < 0) ;
2493 // Put pivot in the right location.
2494 Swap(left, (hi - 1));
2498 private void Heapsort(int lo, int hi)
2500 int n = hi - lo + 1;
2501 for (int i = n / 2; i >= 1; i = i - 1)
2505 for (int i = n; i > 1; i = i - 1)
2507 Swap(lo, lo + i - 1);
2509 DownHeap(1, i - 1, lo);
2513 private void DownHeap(int i, int n, int lo)
2515 Object d = keys.GetValue(lo + i - 1);
2516 Object dt = (items != null)? items.GetValue(lo + i - 1) : null;
2521 if (child < n && comparer.Compare(keys.GetValue(lo + child - 1), keys.GetValue(lo + child)) < 0)
2526 if (!(comparer.Compare(d, keys.GetValue(lo + child - 1)) < 0))
2529 keys.SetValue(keys.GetValue(lo + child - 1), lo + i - 1);
2531 items.SetValue(items.GetValue(lo + child - 1), lo + i - 1);
2534 keys.SetValue(d, lo + i - 1);
2536 items.SetValue(dt, lo + i - 1);
2539 private void InsertionSort(int lo, int hi)
2543 for (i = lo; i < hi; i++)
2546 t = keys.GetValue(i + 1);
2547 dt = (items != null)? items.GetValue(i + 1) : null;
2549 while (j >= lo && comparer.Compare(t, keys.GetValue(j)) < 0)
2551 keys.SetValue(keys.GetValue(j), j + 1);
2553 items.SetValue(items.GetValue(j), j + 1);
2557 keys.SetValue(t, j + 1);
2559 items.SetValue(dt, j + 1);
2564 [Serializable] private sealed class SZArrayEnumerator : IEnumerator, ICloneable
2566 private Array _array;
2568 private int _endIndex; // cache array length, since it's a little slow.
2570 internal SZArrayEnumerator(Array array) {
2571 Contract.Assert(array.Rank == 1 && array.GetLowerBound(0) == 0, "SZArrayEnumerator only works on single dimension arrays w/ a lower bound of zero.");
2574 _endIndex = array.Length;
2577 public Object Clone()
2579 return MemberwiseClone();
2582 public bool MoveNext() {
2583 if (_index < _endIndex) {
2585 return (_index < _endIndex);
2590 public Object Current {
2592 if (_index < 0) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumNotStarted);
2593 if (_index >= _endIndex) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumEnded);
2594 return _array.GetValue(_index);
2598 public void Reset() {
2603 [Serializable] private sealed class ArrayEnumerator : IEnumerator, ICloneable
2605 private Array array;
2607 private int endIndex;
2608 private int startIndex; // Save for Reset.
2609 private int[] _indices; // The current position in a multidim array
2610 private bool _complete;
2612 internal ArrayEnumerator(Array array, int index, int count) {
2614 this.index = index - 1;
2616 endIndex = index + count;
2617 _indices = new int[array.Rank];
2618 int checkForZero = 1; // Check for dimensions of size 0.
2619 for(int i=0; i<array.Rank; i++) {
2620 _indices[i] = array.GetLowerBound(i);
2621 checkForZero *= array.GetLength(i);
2623 // To make MoveNext simpler, decrement least significant index.
2624 _indices[_indices.Length-1]--;
2625 _complete = (checkForZero == 0);
2628 private void IncArray() {
2629 // This method advances us to the next valid array index,
2630 // handling all the multiple dimension & bounds correctly.
2631 // Think of it like an odometer in your car - we start with
2632 // the last digit, increment it, and check for rollover. If
2633 // it rolls over, we set all digits to the right and including
2634 // the current to the appropriate lower bound. Do these overflow
2635 // checks for each dimension, and if the most significant digit
2636 // has rolled over it's upper bound, we're done.
2638 int rank = array.Rank;
2640 for(int dim=rank-1; dim>=0; dim--) {
2641 if (_indices[dim] > array.GetUpperBound(dim)) {
2646 for(int j=dim; j<rank; j++)
2647 _indices[j] = array.GetLowerBound(j);
2653 public Object Clone()
2655 return MemberwiseClone();
2658 public bool MoveNext() {
2668 public Object Current {
2670 if (index < startIndex) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumNotStarted);
2671 if (_complete) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumEnded);
2672 return array.GetValue(_indices);
2676 public void Reset() {
2677 index = startIndex - 1;
2678 int checkForZero = 1;
2679 for(int i=0; i<array.Rank; i++) {
2680 _indices[i] = array.GetLowerBound(i);
2681 checkForZero *= array.GetLength(i);
2683 _complete = (checkForZero == 0);
2684 // To make MoveNext simpler, decrement least significant index.
2685 _indices[_indices.Length-1]--;
2690 // if this is an array of value classes and that value class has a default constructor
2691 // then this calls this default constructor on every element in the value class array.
2692 // otherwise this is a no-op. Generally this method is called automatically by the compiler
2693 [System.Security.SecuritySafeCritical] // auto-generated
2694 [MethodImplAttribute(MethodImplOptions.InternalCall)]
2695 public extern void Initialize();
2704 //----------------------------------------------------------------------------------------
2705 // ! READ THIS BEFORE YOU WORK ON THIS CLASS.
2707 // The methods on this class must be written VERY carefully to avoid introducing security holes.
2708 // That's because they are invoked with special "this"! The "this" object
2709 // for all of these methods are not SZArrayHelper objects. Rather, they are of type U[]
2710 // where U[] is castable to T[]. No actual SZArrayHelper object is ever instantiated. Thus, you will
2711 // see a lot of expressions that cast "this" "T[]".
2713 // This class is needed to allow an SZ array of type T[] to expose IList<T>,
2714 // IList<T.BaseType>, etc., etc. all the way up to IList<Object>. When the following call is
2717 // ((IList<T>) (new U[n])).SomeIListMethod()
2719 // the interface stub dispatcher treats this as a special case, loads up SZArrayHelper,
2720 // finds the corresponding generic method (matched simply by method name), instantiates
2721 // it for type <T> and executes it.
2723 // The "T" will reflect the interface used to invoke the method. The actual runtime "this" will be
2724 // array that is castable to "T[]" (i.e. for primitivs and valuetypes, it will be exactly
2725 // "T[]" - for orefs, it may be a "U[]" where U derives from T.)
2726 //----------------------------------------------------------------------------------------
2727 sealed class SZArrayHelper {
2728 // It is never legal to instantiate this class.
2729 private SZArrayHelper() {
2730 Contract.Assert(false, "Hey! How'd I get here?");
2733 // -----------------------------------------------------------
2734 // ------- Implement IEnumerable<T> interface methods --------
2735 // -----------------------------------------------------------
2736 [SecuritySafeCritical]
2737 internal IEnumerator<T> GetEnumerator<T>() {
2738 //! Warning: "this" is an array, not an SZArrayHelper. See comments above
2739 //! or you may introduce a security hole!
2740 T[] _this = JitHelpers.UnsafeCast<T[]>(this);
2741 int length = _this.Length;
2742 return length == 0 ? SZGenericArrayEnumerator<T>.Empty : new SZGenericArrayEnumerator<T>(_this, length);
2745 // -----------------------------------------------------------
2746 // ------- Implement ICollection<T> interface methods --------
2747 // -----------------------------------------------------------
2748 [SecuritySafeCritical]
2749 void CopyTo<T>(T[] array, int index) {
2750 //! Warning: "this" is an array, not an SZArrayHelper. See comments above
2751 //! or you may introduce a security hole!
2753 T[] _this = JitHelpers.UnsafeCast<T[]>(this);
2754 Array.Copy(_this, 0, array, index, _this.Length);
2757 [SecuritySafeCritical]
2758 internal int get_Count<T>() {
2759 //! Warning: "this" is an array, not an SZArrayHelper. See comments above
2760 //! or you may introduce a security hole!
2761 T[] _this = JitHelpers.UnsafeCast<T[]>(this);
2762 return _this.Length;
2765 // -----------------------------------------------------------
2766 // ---------- Implement IList<T> interface methods -----------
2767 // -----------------------------------------------------------
2768 [SecuritySafeCritical]
2769 internal T get_Item<T>(int index) {
2770 //! Warning: "this" is an array, not an SZArrayHelper. See comments above
2771 //! or you may introduce a security hole!
2772 T[] _this = JitHelpers.UnsafeCast<T[]>(this);
2773 if ((uint)index >= (uint)_this.Length) {
2774 ThrowHelper.ThrowArgumentOutOfRange_IndexException();
2777 return _this[index];
2780 [SecuritySafeCritical]
2781 internal void set_Item<T>(int index, T value) {
2782 //! Warning: "this" is an array, not an SZArrayHelper. See comments above
2783 //! or you may introduce a security hole!
2784 T[] _this = JitHelpers.UnsafeCast<T[]>(this);
2785 if ((uint)index >= (uint)_this.Length) {
2786 ThrowHelper.ThrowArgumentOutOfRange_IndexException();
2789 _this[index] = value;
2792 void Add<T>(T value) {
2793 // Not meaningful for arrays.
2794 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_FixedSizeCollection);
2797 [SecuritySafeCritical]
2798 bool Contains<T>(T value) {
2799 //! Warning: "this" is an array, not an SZArrayHelper. See comments above
2800 //! or you may introduce a security hole!
2801 T[] _this = JitHelpers.UnsafeCast<T[]>(this);
2802 return Array.IndexOf(_this, value) != -1;
2805 bool get_IsReadOnly<T>() {
2810 //! Warning: "this" is an array, not an SZArrayHelper. See comments above
2811 //! or you may introduce a security hole!
2813 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
2816 [SecuritySafeCritical]
2817 int IndexOf<T>(T value) {
2818 //! Warning: "this" is an array, not an SZArrayHelper. See comments above
2819 //! or you may introduce a security hole!
2820 T[] _this = JitHelpers.UnsafeCast<T[]>(this);
2821 return Array.IndexOf(_this, value);
2824 void Insert<T>(int index, T value) {
2825 // Not meaningful for arrays
2826 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_FixedSizeCollection);
2829 bool Remove<T>(T value) {
2830 // Not meaningful for arrays
2831 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_FixedSizeCollection);
2832 return default(bool);
2835 void RemoveAt<T>(int index) {
2836 // Not meaningful for arrays
2837 ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_FixedSizeCollection);
2840 // This is a normal generic Enumerator for SZ arrays. It doesn't have any of the "this" stuff
2841 // that SZArrayHelper does.
2843 [Serializable] private sealed class SZGenericArrayEnumerator<T> : IEnumerator<T> {
2846 private int _endIndex; // cache array length, since it's a little slow.
2848 // Passing -1 for endIndex so that MoveNext always returns false without mutating _index
2849 internal static readonly SZGenericArrayEnumerator<T> Empty = new SZGenericArrayEnumerator<T>(null, -1);
2851 internal SZGenericArrayEnumerator(T[] array, int endIndex) {
2852 // We allow passing null array in case of empty enumerator.
2853 Contract.Assert(array != null || endIndex == -1, "endIndex should be -1 in the case of a null array (for the empty enumerator).");
2856 _endIndex = endIndex;
2859 public bool MoveNext() {
2860 if (_index < _endIndex) {
2862 return (_index < _endIndex);
2869 if (_index < 0) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumNotStarted);
2870 if (_index >= _endIndex) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumEnded);
2871 return _array[_index];
2875 object IEnumerator.Current {
2881 void IEnumerator.Reset() {
2885 public void Dispose()
2892 // Useful in number of places that return an empty byte array to avoid unnecessary memory allocation.
2893 internal static class EmptyArray<T>
2895 public static readonly T[] Value = new T[0];