[runtime] Fix Empty generic enumerator equality
[mono.git] / mcs / class / corlib / System / Array.cs
1 //
2 // System.Array.cs
3 //
4 // Authors:
5 //   Joe Shaw (joe@ximian.com)
6 //   Martin Baulig (martin@gnome.org)
7 //   Dietmar Maurer (dietmar@ximian.com)
8 //   Gonzalo Paniagua Javier (gonzalo@ximian.com)
9 //   Jeffrey Stedfast (fejj@novell.com)
10 //   Marek Safar (marek.safar@gmail.com)
11 //
12 // (C) 2001-2003 Ximian, Inc.  http://www.ximian.com
13 // Copyright (C) 2004-2011 Novell, Inc (http://www.novell.com)
14 // Copyright (C) 2011 Xamarin Inc (http://www.xamarin.com)
15 //
16 // Permission is hereby granted, free of charge, to any person obtaining
17 // a copy of this software and associated documentation files (the
18 // "Software"), to deal in the Software without restriction, including
19 // without limitation the rights to use, copy, modify, merge, publish,
20 // distribute, sublicense, and/or sell copies of the Software, and to
21 // permit persons to whom the Software is furnished to do so, subject to
22 // the following conditions:
23 // 
24 // The above copyright notice and this permission notice shall be
25 // included in all copies or substantial portions of the Software.
26 // 
27 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 //
35
36 using System.Collections;
37 using System.Runtime.CompilerServices;
38 using System.Runtime.InteropServices;
39
40 using System.Collections.Generic;
41 using System.Collections.ObjectModel;
42 using System.Runtime.ConstrainedExecution;
43
44 namespace System
45 {
46         public abstract partial class Array
47         {
48                 // Constructor
49                 private Array ()
50                 {
51                 }
52
53                 /*
54                  * These methods are used to implement the implicit generic interfaces 
55                  * implemented by arrays in NET 2.0.
56                  * Only make those methods generic which really need it, to avoid
57                  * creating useless instantiations.
58                  */
59                 internal int InternalArray__ICollection_get_Count ()
60                 {
61                         return Length;
62                 }
63
64                 internal bool InternalArray__ICollection_get_IsReadOnly ()
65                 {
66                         return true;
67                 }
68
69                 internal IEnumerator<T> InternalArray__IEnumerable_GetEnumerator<T> ()
70                 {
71                         if (Length == 0)
72                                 return EmptyInternalEnumerator<T>.Value;
73                         else
74                                 return new InternalEnumerator<T> (this);
75                 }
76
77                 internal void InternalArray__ICollection_Clear ()
78                 {
79                         throw new NotSupportedException ("Collection is read-only");
80                 }
81
82                 internal void InternalArray__ICollection_Add<T> (T item)
83                 {
84                         throw new NotSupportedException ("Collection is of a fixed size");
85                 }
86
87                 internal bool InternalArray__ICollection_Remove<T> (T item)
88                 {
89                         throw new NotSupportedException ("Collection is of a fixed size");
90                 }
91
92                 internal bool InternalArray__ICollection_Contains<T> (T item)
93                 {
94                         if (this.Rank > 1)
95                                 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
96
97                         int length = this.Length;
98                         for (int i = 0; i < length; i++) {
99                                 T value;
100                                 GetGenericValueImpl (i, out value);
101                                 if (item == null){
102                                         if (value == null) {
103                                                 return true;
104                                         }
105
106                                         continue;
107                                 }
108
109                                 if (item.Equals (value)) {
110                                         return true;
111                                 }
112                         }
113
114                         return false;
115                 }
116
117                 internal void InternalArray__ICollection_CopyTo<T> (T[] array, int arrayIndex)
118                 {
119                         Copy (this, GetLowerBound (0), array, arrayIndex, Length);
120                 }
121
122                 internal T InternalArray__IReadOnlyList_get_Item<T> (int index)
123                 {
124                         if (unchecked ((uint) index) >= unchecked ((uint) Length))
125                                 throw new ArgumentOutOfRangeException ("index");
126
127                         T value;
128                         GetGenericValueImpl (index, out value);
129                         return value;
130                 }
131
132                 internal int InternalArray__IReadOnlyCollection_get_Count ()
133                 {
134                         return Length;
135                 }
136
137                 internal void InternalArray__Insert<T> (int index, T item)
138                 {
139                         throw new NotSupportedException ("Collection is of a fixed size");
140                 }
141
142                 internal void InternalArray__RemoveAt (int index)
143                 {
144                         throw new NotSupportedException ("Collection is of a fixed size");
145                 }
146
147                 internal int InternalArray__IndexOf<T> (T item)
148                 {
149                         if (this.Rank > 1)
150                                 throw new RankException (Locale.GetText ("Only single dimension arrays are supported."));
151
152                         int length = this.Length;
153                         for (int i = 0; i < length; i++) {
154                                 T value;
155                                 GetGenericValueImpl (i, out value);
156                                 if (item == null){
157                                         if (value == null)
158                                                 return i + this.GetLowerBound (0);
159
160                                         continue;
161                                 }
162                                 if (value.Equals (item))
163                                         // array index may not be zero-based.
164                                         // use lower bound
165                                         return i + this.GetLowerBound (0);
166                         }
167
168                         unchecked {
169                                 // lower bound may be MinValue
170                                 return this.GetLowerBound (0) - 1;
171                         }
172                 }
173
174                 internal T InternalArray__get_Item<T> (int index)
175                 {
176                         if (unchecked ((uint) index) >= unchecked ((uint) Length))
177                                 throw new ArgumentOutOfRangeException ("index");
178
179                         T value;
180                         GetGenericValueImpl (index, out value);
181                         return value;
182                 }
183
184                 internal void InternalArray__set_Item<T> (int index, T item)
185                 {
186                         if (unchecked ((uint) index) >= unchecked ((uint) Length))
187                                 throw new ArgumentOutOfRangeException ("index");
188
189                         object[] oarray = this as object [];
190                         if (oarray != null) {
191                                 oarray [index] = (object)item;
192                                 return;
193                         }
194                         SetGenericValueImpl (index, ref item);
195                 }
196
197                 // CAUTION! No bounds checking!
198                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
199                 internal extern void GetGenericValueImpl<T> (int pos, out T value);
200
201                 // CAUTION! No bounds checking!
202                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
203                 internal extern void SetGenericValueImpl<T> (int pos, ref T value);
204
205                 internal struct InternalEnumerator<T> : IEnumerator<T>
206                 {
207                         const int NOT_STARTED = -2;
208                         
209                         // this MUST be -1, because we depend on it in move next.
210                         // we just decr the size, so, 0 - 1 == FINISHED
211                         const int FINISHED = -1;
212                         
213                         readonly Array array;
214                         int idx;
215
216                         internal InternalEnumerator (Array array)
217                         {
218                                 this.array = array;
219                                 idx = NOT_STARTED;
220                         }
221
222                         public void Dispose ()
223                         {
224                         }
225
226                         public bool MoveNext ()
227                         {
228                                 if (idx == NOT_STARTED)
229                                         idx = array.Length;
230
231                                 return idx != FINISHED && -- idx != FINISHED;
232                         }
233
234                         public T Current {
235                                 get {
236                                         if (idx == NOT_STARTED)
237                                                 throw new InvalidOperationException ("Enumeration has not started. Call MoveNext");
238                                         if (idx == FINISHED)
239                                                 throw new InvalidOperationException ("Enumeration already finished");
240
241                                         return array.InternalArray__get_Item<T> (array.Length - 1 - idx);
242                                 }
243                         }
244
245                         void IEnumerator.Reset ()
246                         {
247                                 idx = NOT_STARTED;
248                         }
249
250                         object IEnumerator.Current {
251                                 get {
252                                         return Current;
253                                 }
254                         }
255                 }
256
257                 // Properties
258                 public int Length {
259                         [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
260                         get {
261                                 int length = this.GetLength (0);
262
263                                 for (int i = 1; i < this.Rank; i++) {
264                                         length *= this.GetLength (i); 
265                                 }
266                                 return length;
267                         }
268                 }
269
270                 public int Rank {
271                         [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
272                         get {
273                                 return this.GetRank ();
274                         }
275                 }
276
277                 internal class EmptyInternalEnumerator<T> : IEnumerator<T>
278                 {
279                         public static readonly EmptyInternalEnumerator<T> Value = new EmptyInternalEnumerator<T> ();
280
281                         public void Dispose ()
282                         {
283                                 return;
284                         }
285
286                         public bool MoveNext ()
287                         {
288                                 return false;
289                         }
290
291                         public T Current {
292                                 get {
293                                         throw new InvalidOperationException ("Enumeration has not started. Call MoveNext");
294                                 }
295                         }
296
297                         object IEnumerator.Current {
298                                 get {
299                                         return Current;
300                                 }
301                         }
302
303                         void IEnumerator.Reset ()
304                         {
305                                 return;
306                         }
307                 }
308
309                 // InternalCall Methods
310                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
311                 extern int GetRank ();
312
313                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
314                 public extern int GetLength (int dimension);
315
316                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
317                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
318                 public extern int GetLowerBound (int dimension);
319
320                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
321                 public extern object GetValue (params int[] indices);
322
323                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
324                 public extern void SetValue (object value, params int[] indices);
325
326                 // CAUTION! No bounds checking!
327                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
328                 internal extern object GetValueImpl (int pos);
329
330                 // CAUTION! No bounds checking!
331                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
332                 internal extern void SetValueImpl (object value, int pos);
333
334                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
335                 internal extern static bool FastCopy (Array source, int source_idx, Array dest, int dest_idx, int length);
336
337                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
338                 internal extern static Array CreateInstanceImpl (Type elementType, int[] lengths, int[] bounds);
339
340                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
341                 public int GetUpperBound (int dimension)
342                 {
343                         return GetLowerBound (dimension) + GetLength (dimension) - 1;
344                 }
345
346                 public object GetValue (int index)
347                 {
348                         if (Rank != 1)
349                                 throw new ArgumentException (SR.Arg_RankMultiDimNotSupported);
350
351                         var lb  = GetLowerBound (0);
352                         if (index < lb || index > GetUpperBound (0))
353                                 throw new IndexOutOfRangeException (Locale.GetText (
354                                         "Index has to be between upper and lower bound of the array."));
355
356                         if (GetType ().GetElementType ().IsPointer)
357                                 throw new NotSupportedException ("Type is not supported");
358
359                         return GetValueImpl (index - lb);
360                 }
361
362                 public object GetValue (int index1, int index2)
363                 {
364                         int[] ind = {index1, index2};
365                         return GetValue (ind);
366                 }
367
368                 public object GetValue (int index1, int index2, int index3)
369                 {
370                         int[] ind = {index1, index2, index3};
371                         return GetValue (ind);
372                 }
373
374                 public void SetValue (object value, int index)
375                 {
376                         if (Rank != 1)
377                                 throw new ArgumentException (SR.Arg_RankMultiDimNotSupported);
378
379                         var lb  = GetLowerBound (0);
380                         if (index < lb || index > GetUpperBound (0))
381                                 throw new IndexOutOfRangeException (Locale.GetText (
382                                         "Index has to be >= lower bound and <= upper bound of the array."));
383
384                         if (GetType ().GetElementType ().IsPointer)
385                                 throw new NotSupportedException ("Type is not supported");
386
387                         SetValueImpl (value, index - lb);
388                 }
389
390                 public void SetValue (object value, int index1, int index2)
391                 {
392                         int[] ind = {index1, index2};
393                         SetValue (value, ind);
394                 }
395
396                 public void SetValue (object value, int index1, int index2, int index3)
397                 {
398                         int[] ind = {index1, index2, index3};
399                         SetValue (value, ind);
400                 }
401
402                 internal static Array UnsafeCreateInstance(Type elementType, int[] lengths, int[] lowerBounds)
403                 {
404                         return CreateInstance(elementType, lengths, lowerBounds);
405                 }
406
407                 internal static Array UnsafeCreateInstance (Type elementType, int length1, int length2)
408                 {
409                         return CreateInstance (elementType, length1, length2);
410                 }
411
412                 internal static Array UnsafeCreateInstance (Type elementType, params int[] lengths)
413                 {
414                         return CreateInstance(elementType, lengths);
415                 }
416
417                 public static Array CreateInstance (Type elementType, int length)
418                 {
419                         int[] lengths = {length};
420
421                         return CreateInstance (elementType, lengths);
422                 }
423
424                 public static Array CreateInstance (Type elementType, int length1, int length2)
425                 {
426                         int[] lengths = {length1, length2};
427
428                         return CreateInstance (elementType, lengths);
429                 }
430
431                 public static Array CreateInstance (Type elementType, int length1, int length2, int length3)
432                 {
433                         int[] lengths = {length1, length2, length3};
434
435                         return CreateInstance (elementType, lengths);
436                 }
437
438                 public static Array CreateInstance (Type elementType, params int[] lengths)
439                 {
440                         if (elementType == null)
441                                 throw new ArgumentNullException ("elementType");
442                         if (lengths == null)
443                                 throw new ArgumentNullException ("lengths");
444
445                         if (lengths.Length > 255)
446                                 throw new TypeLoadException ();
447
448                         int[] bounds = null;
449
450                         elementType = elementType.UnderlyingSystemType as RuntimeType;
451                         if (elementType == null)
452                                 throw new ArgumentException ("Type must be a type provided by the runtime.", "elementType");
453                         if (elementType.Equals (typeof (void)))
454                                 throw new NotSupportedException ("Array type can not be void");
455                         if (elementType.ContainsGenericParameters)
456                                 throw new NotSupportedException ("Array type can not be an open generic type");
457                         
458                         return CreateInstanceImpl (elementType, lengths, bounds);
459                 }
460
461                 public static Array CreateInstance (Type elementType, int[] lengths, int [] lowerBounds)
462                 {
463                         if (elementType == null)
464                                 throw new ArgumentNullException ("elementType");
465                         if (lengths == null)
466                                 throw new ArgumentNullException ("lengths");
467                         if (lowerBounds == null)
468                                 throw new ArgumentNullException ("lowerBounds");
469
470                         elementType = elementType.UnderlyingSystemType as RuntimeType;
471                         if (elementType == null)
472                                 throw new ArgumentException ("Type must be a type provided by the runtime.", "elementType");
473                         if (elementType.Equals (typeof (void)))
474                                 throw new NotSupportedException ("Array type can not be void");
475                         if (elementType.ContainsGenericParameters)
476                                 throw new NotSupportedException ("Array type can not be an open generic type");
477
478                         if (lengths.Length < 1)
479                                 throw new ArgumentException (Locale.GetText ("Arrays must contain >= 1 elements."));
480
481                         if (lengths.Length != lowerBounds.Length)
482                                 throw new ArgumentException (Locale.GetText ("Arrays must be of same size."));
483
484                         for (int j = 0; j < lowerBounds.Length; j ++) {
485                                 if (lengths [j] < 0)
486                                         throw new ArgumentOutOfRangeException ("lengths", Locale.GetText (
487                                                 "Each value has to be >= 0."));
488                                 if ((long)lowerBounds [j] + (long)lengths [j] > (long)Int32.MaxValue)
489                                         throw new ArgumentOutOfRangeException ("lengths", Locale.GetText (
490                                                 "Length + bound must not exceed Int32.MaxValue."));
491                         }
492
493                         if (lengths.Length > 255)
494                                 throw new TypeLoadException ();
495
496                         return CreateInstanceImpl (elementType, lengths, lowerBounds);
497                 }
498
499                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
500                 public static void Clear (Array array, int index, int length)
501                 {
502                         if (array == null)
503                                 throw new ArgumentNullException ("array");
504                         if (length < 0)
505                                 throw new IndexOutOfRangeException ("length < 0");
506
507                         int low = array.GetLowerBound (0);
508                         if (index < low)
509                                 throw new IndexOutOfRangeException ("index < lower bound");
510                         index = index - low;
511
512                         // re-ordered to avoid possible integer overflow
513                         if (index > array.Length - length)
514                                 throw new IndexOutOfRangeException ("index + length > size");
515
516                         ClearInternal (array, index, length);
517                 }
518                 
519                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
520                 static extern void ClearInternal (Array a, int index, int count);
521
522                 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
523                 public static void Copy (Array sourceArray, Array destinationArray, int length)
524                 {
525                         // need these checks here because we are going to use
526                         // GetLowerBound() on source and dest.
527                         if (sourceArray == null)
528                                 throw new ArgumentNullException ("sourceArray");
529
530                         if (destinationArray == null)
531                                 throw new ArgumentNullException ("destinationArray");
532
533                         Copy (sourceArray, sourceArray.GetLowerBound (0), destinationArray,
534                                 destinationArray.GetLowerBound (0), length);
535                 }
536
537                 [ReliabilityContractAttribute (Consistency.MayCorruptInstance, Cer.MayFail)]
538                 public static void Copy (Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length)
539                 {
540                         if (sourceArray == null)
541                                 throw new ArgumentNullException ("sourceArray");
542
543                         if (destinationArray == null)
544                                 throw new ArgumentNullException ("destinationArray");
545
546                         if (length < 0)
547                                 throw new ArgumentOutOfRangeException ("length", Locale.GetText (
548                                         "Value has to be >= 0."));;
549
550                         if (sourceArray.Rank != destinationArray.Rank)
551                                 throw new RankException(SR.Rank_MultiDimNotSupported);
552
553                         if (sourceIndex < 0)
554                                 throw new ArgumentOutOfRangeException ("sourceIndex", Locale.GetText (
555                                         "Value has to be >= 0."));;
556
557                         if (destinationIndex < 0)
558                                 throw new ArgumentOutOfRangeException ("destinationIndex", Locale.GetText (
559                                         "Value has to be >= 0."));;
560
561                         if (FastCopy (sourceArray, sourceIndex, destinationArray, destinationIndex, length))
562                                 return;
563
564                         int source_pos = sourceIndex - sourceArray.GetLowerBound (0);
565                         int dest_pos = destinationIndex - destinationArray.GetLowerBound (0);
566
567                         if (dest_pos < 0)
568                                 throw new ArgumentOutOfRangeException ("destinationIndex", "Index was less than the array's lower bound in the first dimension.");
569
570                         // re-ordered to avoid possible integer overflow
571                         if (source_pos > sourceArray.Length - length)
572                                 throw new ArgumentException ("length");
573
574                         if (dest_pos > destinationArray.Length - length) {
575                                 string msg = "Destination array was not long enough. Check " +
576                                         "destIndex and length, and the array's lower bounds";
577                                 throw new ArgumentException (msg, string.Empty);
578                         }
579
580                         Type src_type = sourceArray.GetType ().GetElementType ();
581                         Type dst_type = destinationArray.GetType ().GetElementType ();
582
583                         if (!Object.ReferenceEquals (sourceArray, destinationArray) || source_pos > dest_pos) {
584                                 for (int i = 0; i < length; i++) {
585                                         Object srcval = sourceArray.GetValueImpl (source_pos + i);
586
587                                         try {
588                                                 destinationArray.SetValueImpl (srcval, dest_pos + i);
589                                         } catch (ArgumentException) {
590                                                 throw CreateArrayTypeMismatchException ();
591                                         } catch {
592                                                 if (CanAssignArrayElement (src_type, dst_type))
593                                                         throw;
594
595                                                 throw CreateArrayTypeMismatchException ();
596                                         }
597                                 }
598                         }
599                         else {
600                                 for (int i = length - 1; i >= 0; i--) {
601                                         Object srcval = sourceArray.GetValueImpl (source_pos + i);
602
603                                         try {
604                                                 destinationArray.SetValueImpl (srcval, dest_pos + i);
605                                         } catch (ArgumentException) {
606                                                 throw CreateArrayTypeMismatchException ();
607                                         } catch {
608                                                 if (CanAssignArrayElement (src_type, dst_type))
609                                                         throw;
610
611                                                 throw CreateArrayTypeMismatchException ();
612                                         }
613                                 }
614                         }
615                 }
616
617                 static Exception CreateArrayTypeMismatchException ()
618                 {
619                         return new ArrayTypeMismatchException ();
620                 }
621
622                 static bool CanAssignArrayElement (Type source, Type target)
623                 {
624                         if (source.IsValueType)
625                                 return source.IsAssignableFrom (target);
626
627                         if (source.IsInterface)
628                                 return !target.IsValueType;
629
630                         if (target.IsInterface)
631                                 return !source.IsValueType;
632
633                         return source.IsAssignableFrom (target) || target.IsAssignableFrom (source);
634                 }
635
636                 [ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
637                 //
638                 // The constrained copy should guarantee that if there is an exception thrown
639                 // during the copy, the destination array remains unchanged.
640                 // This is related to System.Runtime.Reliability.CER
641                 public static void ConstrainedCopy (Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length)
642                 {
643                         Copy (sourceArray, sourceIndex, destinationArray, destinationIndex, length);
644                 }
645
646                 public static T[] Empty<T>()
647                 {
648                         return EmptyArray<T>.Value;
649                 }
650
651                 public void Initialize()
652                 {
653                         return;
654                 }
655
656                 static int IndexOfImpl<T>(T[] array, T value, int startIndex, int count)
657                 {
658                         return EqualityComparer<T>.Default.IndexOf (array, value, startIndex, count);
659                 }
660
661                 static int LastIndexOfImpl<T>(T[] array, T value, int startIndex, int count)
662                 {
663                         return EqualityComparer<T>.Default.LastIndexOf (array, value, startIndex, count);
664                 }
665
666                 static void SortImpl (Array keys, Array items, int index, int length, IComparer comparer)
667                 {
668                         Object[] objKeys = keys as Object[];
669                         Object[] objItems = null;
670                         if (objKeys != null)
671                                 objItems = items as Object[];
672
673                         if (objKeys != null && (items == null || objItems != null)) {
674                                 SorterObjectArray sorter = new SorterObjectArray(objKeys, objItems, comparer);
675                                 sorter.Sort(index, length);
676                         } else {
677                                 SorterGenericArray sorter = new SorterGenericArray(keys, items, comparer);
678                                 sorter.Sort(index, length);
679                         }
680                 }
681
682                 #region Unsafe array operations
683
684                 //
685                 // Loads array index with no safety checks (JIT intristics)
686                 //
687                 internal static T UnsafeLoad<T> (T[] array, int index) {
688                         return array [index];
689                 }
690
691                 //
692                 // Stores values at specified array index with no safety checks (JIT intristics)
693                 //
694                 internal static void UnsafeStore<T> (T[] array, int index, T value) {
695                         array [index] = value;
696                 }
697
698                 //
699                 // Moved value from instance into target of different type with no checks (JIT intristics)
700                 //
701                 // Restrictions:
702                 //
703                 // S and R must either:
704                 //       both be blitable valuetypes
705                 //       both be reference types (IOW, an unsafe cast)
706                 // S and R cannot be float or double
707                 // S and R must either:
708                 //       both be a struct
709                 //       both be a scalar
710                 // S and R must either:
711                 //       be of same size
712                 //       both be a scalar of size <= 4
713                 //
714                 internal static R UnsafeMov<S,R> (S instance) {
715                         return (R)(object) instance;
716                 }
717
718                 #endregion
719
720                 internal sealed class FunctorComparer<T> : IComparer<T> {
721                         Comparison<T> comparison;
722
723                         public FunctorComparer(Comparison<T> comparison) {
724                                 this.comparison = comparison;
725                         }
726
727                         public int Compare(T x, T y) {
728                                 return comparison(x, y);
729                         }
730                 }
731
732                 partial class ArrayEnumerator
733                 {
734                         public Object Current {
735                                 get {
736                                         if (_index < 0) throw new InvalidOperationException (SR.InvalidOperation_EnumNotStarted);
737                                         if (_index >= _endIndex) throw new InvalidOperationException (SR.InvalidOperation_EnumEnded);
738                                         if (_index == 0 && _array.GetType ().GetElementType ().IsPointer) throw new NotSupportedException ("Type is not supported");
739                                         return _array.GetValueImpl(_index);
740                                 }
741                         }
742                 }
743         }
744 }