Some more style nits
[mono.git] / mcs / class / System.Data / System.Data.Common / DataContainer.cs
1 //
2 // Copyright (C) 2008 Novell, Inc (http://www.novell.com)
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 //
23 using System;
24 using System.Collections;
25
26 namespace System.Data.Common
27 {
28         internal abstract class DataContainer {
29                 BitArray null_values;
30                 System.Type _type;
31                 DataColumn _column;
32
33                 // implementing class protocol
34                 protected abstract object GetValue (int index);
35                 internal abstract long GetInt64 (int index);
36
37                 // used to set the array value to something neutral when the corresponding item is null (in the database sense)
38                 // note: we don't actually ever look at the value written there, but the GC may like us to avoid keeping stale
39                 // values in the array.
40                 protected abstract void ZeroOut (int index);
41                 protected abstract void SetValue (int index, object value);
42                 protected abstract void SetValueFromSafeDataRecord (int index, ISafeDataRecord record, int field);
43
44                 protected abstract void DoCopyValue (DataContainer from, int from_index, int to_index);
45                 protected abstract int DoCompareValues (int index1, int index2);
46
47                 protected abstract void Resize (int length);
48
49                 internal object this [int index] {
50                         get { return IsNull (index) ? DBNull.Value : GetValue (index); }
51                         set {
52                                 if (value == null) {
53                                         CopyValue (Column.Table.DefaultValuesRowIndex, index);
54                                         return;
55                                 }
56
57                                 bool is_dbnull = value == DBNull.Value;
58                                 if (is_dbnull)
59                                         ZeroOut (index);
60                                 else
61                                         SetValue (index, value);
62                                 null_values [index] = is_dbnull;
63                         }
64                 }
65
66                 internal int Capacity {
67                         get { return null_values != null ? null_values.Count : 0; }
68                         set {
69                                 int old_capacity = Capacity;
70                                 if (value == old_capacity)
71                                         return;
72                                 if (null_values == null)
73                                         null_values = new BitArray (value);
74                                 else
75                                         null_values.Length = value;
76                                 Resize (value);
77                         }
78                 }
79
80                 internal Type Type {
81                         get { return _type; }
82                 }
83
84                 protected DataColumn Column {
85                         get { return _column; }
86                 }
87
88                 internal static DataContainer Create (Type type, DataColumn column)
89                 {
90                         DataContainer container;
91                         switch (Type.GetTypeCode(type)) {
92                         case TypeCode.Int16:
93                                 container = new Int16DataContainer ();
94                                 break;
95                         case TypeCode.Int32:
96                                 container = new Int32DataContainer ();
97                                 break;
98                         case TypeCode.Int64:
99                                 container = new Int64DataContainer ();
100                                 break;
101                         case TypeCode.String:
102                                 container = new StringDataContainer ();
103                                 break;
104                         case TypeCode.Boolean:
105                                 container = new BitDataContainer ();
106                                 break;
107                         case TypeCode.Byte:
108                                 container = new ByteDataContainer ();
109                                 break;
110                         case TypeCode.Char:
111                                 container = new CharDataContainer ();
112                                 break;
113                         case TypeCode.Double:
114                                 container = new DoubleDataContainer ();
115                                 break;
116                         case TypeCode.SByte:
117                                 container = new SByteDataContainer ();
118                                 break;
119                         case TypeCode.Single:
120                                 container = new SingleDataContainer ();
121                                 break;
122                         case TypeCode.UInt16:
123                                 container = new UInt16DataContainer ();
124                                 break;
125                         case TypeCode.UInt32:
126                                 container = new UInt32DataContainer ();
127                                 break;
128                         case TypeCode.UInt64:
129                                 container = new UInt64DataContainer ();
130                                 break;
131                         case TypeCode.DateTime:
132                                 container = new DateTimeDataContainer ();
133                                 break;
134                         case TypeCode.Decimal:
135                                 container = new DecimalDataContainer ();
136                                 break;
137                         default:
138                                 container = new ObjectDataContainer ();
139                                 break;
140                         }
141                         container._type = type;
142                         container._column = column;
143                         return container;
144                 }
145
146                 internal bool IsNull (int index)
147                 {
148                         return null_values == null || null_values [index];
149                 }
150
151                 internal void FillValues (int fromIndex)
152                 {
153                         for (int i = 0; i < Capacity; i++)
154                                 CopyValue (fromIndex, i);
155                 }
156
157                 internal void CopyValue (int from_index, int to_index)
158                 {
159                         CopyValue (this, from_index, to_index);
160                 }
161
162                 internal void CopyValue (DataContainer from, int from_index, int to_index)
163                 {
164                         DoCopyValue (from, from_index, to_index);
165                         null_values [to_index] = from.null_values [from_index];
166                 }
167
168                 internal void SetItemFromDataRecord (int index, IDataRecord record, int field)
169                 {
170                         if (record.IsDBNull (field))
171                                 this [index] = DBNull.Value;
172                         else if (record is ISafeDataRecord)
173                                 SetValueFromSafeDataRecord (index, (ISafeDataRecord) record, field);
174                         else
175                                 this [index] = record.GetValue (field);
176                 }
177
178                 internal int CompareValues (int index1, int index2)
179                 {
180                         bool null1 = IsNull (index1);
181                         bool null2 = IsNull (index2);
182
183                         if (null1 == null2)
184                                 return null1 ? 0 : DoCompareValues (index1, index2);
185                         return null1 ? -1 : 1;
186                 }
187         }
188
189         sealed class BitDataContainer : DataContainer {
190                 BitArray _values;
191
192                 protected override object GetValue (int index)
193                 {
194                         return _values [index];
195                 }
196
197                 protected override void ZeroOut (int index)
198                 {
199                         _values [index] = false;
200                 }
201
202                 protected override void SetValue (int index, object value)
203                 {
204                         _values [index] = value is bool ? (bool) value : Convert.ToBoolean (value);
205                 }
206
207                 protected override void SetValueFromSafeDataRecord (int index, ISafeDataRecord record, int field)
208                 {
209                         _values [index] = record.GetBooleanSafe (field);
210                 }
211
212                 protected override void DoCopyValue (DataContainer from, int from_index, int to_index)
213                 {
214                         _values [to_index] = ((BitDataContainer) from)._values [from_index];
215                 }
216
217                 protected override int DoCompareValues (int index1, int index2)
218                 {
219                         bool val1 = _values [index1];
220                         bool val2 = _values [index2];
221                         return val1 == val2 ? 0 : val1 ? 1 : -1;
222                 }
223
224                 protected override void Resize (int size)
225                 {
226                         if (_values == null)
227                                 _values = new BitArray (size);
228                         else
229                                 _values.Length = size;
230                 }
231
232                 internal override long GetInt64 (int index)
233                 {
234                         return Convert.ToInt64 (_values [index]);
235                 }
236         }
237
238         sealed class CharDataContainer : DataContainer {
239                 char [] _values;
240
241                 protected override object GetValue (int index)
242                 {
243                         return _values [index];
244                 }
245
246                 protected override void ZeroOut (int index)
247                 {
248                         _values [index] = '\0';
249                 }
250
251                 protected override void SetValue (int index, object value)
252                 {
253                         _values [index] = value is char ? (char) value : Convert.ToChar (value);
254                 }
255
256                 protected override void SetValueFromSafeDataRecord (int index, ISafeDataRecord record, int field)
257                 {
258                         _values [index] = record.GetCharSafe (field);
259                 }
260
261                 protected override void DoCopyValue (DataContainer from, int from_index, int to_index)
262                 {
263                         _values [to_index] = ((CharDataContainer) from)._values [from_index];
264                 }
265
266                 protected override int DoCompareValues (int index1, int index2)
267                 {
268                         char val1 = _values [index1];
269                         char val2 = _values [index2];
270                         return val1 == val2 ? 0 : val1 < val2 ? -1 : 1;
271                 }
272
273                 protected override void Resize (int size)
274                 {
275                         if (_values == null) {
276                                 _values = new char [size];
277                                 return;
278                         }
279
280                         char[] tmp = new char [size];
281                         Array.Copy (_values, 0, tmp, 0, _values.Length);
282                         _values = tmp;
283                 }
284
285                 internal override long GetInt64 (int index)
286                 {
287                         return Convert.ToInt64 (_values [index]);
288                 }
289         }
290
291         sealed class ByteDataContainer : DataContainer {
292                 byte [] _values;
293
294                 protected override object GetValue (int index)
295                 {
296                         return _values [index];
297                 }
298
299                 protected override void ZeroOut (int index)
300                 {
301                         _values [index] = 0;
302                 }
303
304                 protected override void SetValue (int index, object value)
305                 {
306                         _values [index] = value is byte ? (byte) value : Convert.ToByte (value);
307                 }
308
309                 protected override void SetValueFromSafeDataRecord (int index, ISafeDataRecord record, int field)
310                 {
311                         _values [index] = record.GetByteSafe (field);
312                 }
313
314                 protected override void DoCopyValue (DataContainer from, int from_index, int to_index)
315                 {
316                         _values [to_index] = ((ByteDataContainer) from)._values [from_index];
317                 }
318
319                 protected override int DoCompareValues (int index1, int index2)
320                 {
321                         int val1 = _values [index1];
322                         int val2 = _values [index2];
323                         return val1 - val2;
324                 }
325
326                 protected override void Resize (int size)
327                 {
328                         if (_values == null) {
329                                 _values = new byte [size];
330                                 return;
331                         }
332
333                         byte[] tmp = new byte [size];
334                         Array.Copy (_values, 0, tmp, 0, _values.Length);
335                         _values = tmp;
336                 }
337
338                 internal override long GetInt64 (int index)
339                 {
340                         return _values [index];
341                 }
342         }
343
344         sealed class SByteDataContainer : DataContainer {
345                 sbyte [] _values;
346
347                 protected override object GetValue (int index)
348                 {
349                         return _values [index];
350                 }
351
352                 protected override void ZeroOut (int index)
353                 {
354                         _values [index] = 0;
355                 }
356
357                 protected override void SetValue (int index, object value)
358                 {
359                         _values [index] = value is sbyte ? (sbyte) value : Convert.ToSByte (value);
360                 }
361
362                 protected override void SetValueFromSafeDataRecord (int index, ISafeDataRecord record, int field)
363                 {
364                         _values [index] = (sbyte) record.GetByteSafe (field);
365                 }
366
367                 protected override void DoCopyValue (DataContainer from, int from_index, int to_index)
368                 {
369                         _values [to_index] = ((SByteDataContainer) from)._values [from_index];
370                 }
371
372                 protected override int DoCompareValues (int index1, int index2)
373                 {
374                         int val1 = _values [index1];
375                         int val2 = _values [index2];
376                         return val1 - val2;
377                 }
378
379                 protected override void Resize (int size)
380                 {
381                         if (_values == null) {
382                                 _values = new sbyte [size];
383                                 return;
384                         }
385
386                         sbyte[] tmp = new sbyte [size];
387                         Array.Copy (_values, 0, tmp, 0, _values.Length);
388                         _values = tmp;
389                 }
390
391                 internal override long GetInt64 (int index)
392                 {
393                         return _values [index];
394                 }
395         }
396
397         sealed class Int16DataContainer : DataContainer {
398                 short [] _values;
399
400                 protected override object GetValue (int index)
401                 {
402                         return _values [index];
403                 }
404
405                 protected override void ZeroOut (int index)
406                 {
407                         _values [index] = 0;
408                 }
409
410                 protected override void SetValue (int index, object value)
411                 {
412                         _values [index] = value is short ? (short) value : Convert.ToInt16 (value);
413                 }
414
415                 protected override void SetValueFromSafeDataRecord (int index, ISafeDataRecord record, int field)
416                 {
417                         _values [index] = record.GetInt16Safe (field);
418                 }
419
420                 protected override void DoCopyValue (DataContainer from, int from_index, int to_index)
421                 {
422                         _values [to_index] = ((Int16DataContainer) from)._values [from_index];
423                 }
424
425                 protected override int DoCompareValues (int index1, int index2)
426                 {
427                         int val1 = _values [index1];
428                         int val2 = _values [index2];
429                         return val1 - val2;
430                 }
431
432                 protected override void Resize (int size)
433                 {
434                         if (_values == null) {
435                                 _values = new short [size];
436                                 return;
437                         }
438
439                         short[] tmp = new short [size];
440                         Array.Copy (_values, 0, tmp, 0, _values.Length);
441                         _values = tmp;
442                 }
443
444                 internal override long GetInt64 (int index)
445                 {
446                         return _values [index];
447                 }
448         }
449
450         sealed class UInt16DataContainer : DataContainer {
451                 ushort [] _values;
452
453                 protected override object GetValue (int index)
454                 {
455                         return _values [index];
456                 }
457
458                 protected override void ZeroOut (int index)
459                 {
460                         _values [index] = 0;
461                 }
462
463                 protected override void SetValue (int index, object value)
464                 {
465                         _values [index] = value is ushort ? (ushort) value : Convert.ToUInt16 (value);
466                 }
467
468                 protected override void SetValueFromSafeDataRecord (int index, ISafeDataRecord record, int field)
469                 {
470                         _values [index] = (ushort) record.GetInt16Safe (field);
471                 }
472
473                 protected override void DoCopyValue (DataContainer from, int from_index, int to_index)
474                 {
475                         _values [to_index] = ((UInt16DataContainer) from)._values [from_index];
476                 }
477
478                 protected override int DoCompareValues (int index1, int index2)
479                 {
480                         int val1 = _values [index1];
481                         int val2 = _values [index2];
482                         return val1 - val2;
483                 }
484
485                 protected override void Resize (int size)
486                 {
487                         if (_values == null) {
488                                 _values = new ushort [size];
489                                 return;
490                         }
491
492                         ushort[] tmp = new ushort [size];
493                         Array.Copy (_values, 0, tmp, 0, _values.Length);
494                         _values = tmp;
495                 }
496
497                 internal override long GetInt64 (int index)
498                 {
499                         return _values [index];
500                 }
501         }
502
503         sealed class Int32DataContainer : DataContainer {
504                 int [] _values;
505
506                 protected override object GetValue (int index)
507                 {
508                         return _values [index];
509                 }
510
511                 protected override void ZeroOut (int index)
512                 {
513                         _values [index] = 0;
514                 }
515
516                 protected override void SetValue (int index, object value)
517                 {
518                         _values [index] = value is int ? (int) value : Convert.ToInt32 (value);
519                 }
520
521                 protected override void SetValueFromSafeDataRecord (int index, ISafeDataRecord record, int field)
522                 {
523                         _values [index] = record.GetInt32Safe (field);
524                 }
525
526                 protected override void DoCopyValue (DataContainer from, int from_index, int to_index)
527                 {
528                         _values [to_index] = ((Int32DataContainer) from)._values [from_index];
529                 }
530
531                 protected override int DoCompareValues (int index1, int index2)
532                 {
533                         int val1 = _values [index1];
534                         int val2 = _values [index2];
535                         return val1 == val2 ? 0 : val1 < val2 ? -1 : 1;
536                 }
537
538                 protected override void Resize (int size)
539                 {
540                         if (_values == null) {
541                                 _values = new int [size];
542                                 return;
543                         }
544
545                         int[] tmp = new int [size];
546                         Array.Copy (_values, 0, tmp, 0, _values.Length);
547                         _values = tmp;
548                 }
549
550                 internal override long GetInt64 (int index)
551                 {
552                         return _values [index];
553                 }
554         }
555
556         sealed class UInt32DataContainer : DataContainer {
557                 uint [] _values;
558
559                 protected override object GetValue (int index)
560                 {
561                         return _values [index];
562                 }
563
564                 protected override void ZeroOut (int index)
565                 {
566                         _values [index] = 0;
567                 }
568
569                 protected override void SetValue (int index, object value)
570                 {
571                         _values [index] = value is uint ? (uint) value : Convert.ToUInt32 (value);
572                 }
573
574                 protected override void SetValueFromSafeDataRecord (int index, ISafeDataRecord record, int field)
575                 {
576                         _values [index] = (uint) record.GetInt32Safe (field);
577                 }
578
579                 protected override void DoCopyValue (DataContainer from, int from_index, int to_index)
580                 {
581                         _values [to_index] = ((UInt32DataContainer) from)._values [from_index];
582                 }
583
584                 protected override int DoCompareValues (int index1, int index2)
585                 {
586                         uint val1 = _values [index1];
587                         uint val2 = _values [index2];
588                         return val1 == val2 ? 0 : val1 < val2 ? -1 : 1;
589                 }
590
591                 protected override void Resize (int size)
592                 {
593                         if (_values == null) {
594                                 _values = new uint [size];
595                                 return;
596                         }
597
598                         uint[] tmp = new uint [size];
599                         Array.Copy (_values, 0, tmp, 0, _values.Length);
600                         _values = tmp;
601                 }
602
603                 internal override long GetInt64 (int index)
604                 {
605                         return _values [index];
606                 }
607         }
608
609         sealed class Int64DataContainer : DataContainer {
610                 long [] _values;
611
612                 protected override object GetValue (int index)
613                 {
614                         return _values [index];
615                 }
616
617                 protected override void ZeroOut (int index)
618                 {
619                         _values [index] = 0;
620                 }
621
622                 protected override void SetValue (int index, object value)
623                 {
624                         _values [index] = value is long ? (long) value : Convert.ToInt64 (value);
625                 }
626
627                 protected override void SetValueFromSafeDataRecord (int index, ISafeDataRecord record, int field)
628                 {
629                         _values [index] = record.GetInt64Safe (field);
630                 }
631
632                 protected override void DoCopyValue (DataContainer from, int from_index, int to_index)
633                 {
634                         _values [to_index] = ((Int64DataContainer) from)._values [from_index];
635                 }
636
637                 protected override int DoCompareValues (int index1, int index2)
638                 {
639                         long val1 = _values [index1];
640                         long val2 = _values [index2];
641                         return val1 == val2 ? 0 : val1 < val2 ? -1 : 1;
642                 }
643
644                 protected override void Resize (int size)
645                 {
646                         if (_values == null) {
647                                 _values = new long [size];
648                                 return;
649                         }
650
651                         long[] tmp = new long [size];
652                         Array.Copy (_values, 0, tmp, 0, _values.Length);
653                         _values = tmp;
654                 }
655
656                 internal override long GetInt64 (int index)
657                 {
658                         return _values [index];
659                 }
660         }
661
662         sealed class UInt64DataContainer : DataContainer {
663                 ulong [] _values;
664
665                 protected override object GetValue (int index)
666                 {
667                         return _values [index];
668                 }
669
670                 protected override void ZeroOut (int index)
671                 {
672                         _values [index] = 0;
673                 }
674
675                 protected override void SetValue (int index, object value)
676                 {
677                         _values [index] = value is ulong ? (ulong) value : Convert.ToUInt64 (value);
678                 }
679
680                 protected override void SetValueFromSafeDataRecord (int index, ISafeDataRecord record, int field)
681                 {
682                         _values [index] = (ulong) record.GetInt64Safe (field);
683                 }
684
685                 protected override void DoCopyValue (DataContainer from, int from_index, int to_index)
686                 {
687                         _values [to_index] = ((UInt64DataContainer) from)._values [from_index];
688                 }
689
690                 protected override int DoCompareValues (int index1, int index2)
691                 {
692                         ulong val1 = _values [index1];
693                         ulong val2 = _values [index2];
694                         return val1 == val2 ? 0 : val1 < val2 ? -1 : 1;
695                 }
696
697                 protected override void Resize (int size)
698                 {
699                         if (_values == null) {
700                                 _values = new ulong [size];
701                                 return;
702                         }
703
704                         ulong[] tmp = new ulong [size];
705                         Array.Copy (_values, 0, tmp, 0, _values.Length);
706                         _values = tmp;
707                 }
708
709                 internal override long GetInt64 (int index)
710                 {
711                         return Convert.ToInt64 (_values [index]);
712                 }
713         }
714
715         sealed class SingleDataContainer : DataContainer {
716                 float [] _values;
717
718                 protected override object GetValue (int index)
719                 {
720                         return _values [index];
721                 }
722
723                 protected override void ZeroOut (int index)
724                 {
725                         _values [index] = 0;
726                 }
727
728                 protected override void SetValue (int index, object value)
729                 {
730                         _values [index] = value is float ? (float) value : Convert.ToSingle (value);
731                 }
732
733                 protected override void SetValueFromSafeDataRecord (int index, ISafeDataRecord record, int field)
734                 {
735                         _values [index] = record.GetFloatSafe (field);
736                 }
737
738                 protected override void DoCopyValue (DataContainer from, int from_index, int to_index)
739                 {
740                         _values [to_index] = ((SingleDataContainer) from)._values [from_index];
741                 }
742
743                 protected override int DoCompareValues (int index1, int index2)
744                 {
745                         float val1 = _values [index1];
746                         float val2 = _values [index2];
747                         return val1 == val2 ? 0 : val1 < val2 ? -1 : 1;
748                 }
749
750                 protected override void Resize (int size)
751                 {
752                         if (_values == null) {
753                                 _values = new float [size];
754                                 return;
755                         }
756
757                         float[] tmp = new float [size];
758                         Array.Copy (_values, 0, tmp, 0, _values.Length);
759                         _values = tmp;
760                 }
761
762                 internal override long GetInt64 (int index)
763                 {
764                         return Convert.ToInt64 (_values [index]);
765                 }
766         }
767
768         sealed class DoubleDataContainer : DataContainer {
769                 double [] _values;
770
771                 protected override object GetValue (int index)
772                 {
773                         return _values [index];
774                 }
775
776                 protected override void ZeroOut (int index)
777                 {
778                         _values [index] = 0;
779                 }
780
781                 protected override void SetValue (int index, object value)
782                 {
783                         _values [index] = value is double ? (double) value : Convert.ToDouble (value);
784                 }
785
786                 protected override void SetValueFromSafeDataRecord (int index, ISafeDataRecord record, int field)
787                 {
788                         _values [index] = record.GetDoubleSafe (field);
789                 }
790
791                 protected override void DoCopyValue (DataContainer from, int from_index, int to_index)
792                 {
793                         _values [to_index] = ((DoubleDataContainer) from)._values [from_index];
794                 }
795
796                 protected override int DoCompareValues (int index1, int index2)
797                 {
798                         double val1 = _values [index1];
799                         double val2 = _values [index2];
800                         return val1 == val2 ? 0 : val1 < val2 ? -1 : 1;
801                 }
802
803                 protected override void Resize (int size)
804                 {
805                         if (_values == null) {
806                                 _values = new double [size];
807                                 return;
808                         }
809
810                         double[] tmp = new double [size];
811                         Array.Copy (_values, 0, tmp, 0, _values.Length);
812                         _values = tmp;
813                 }
814
815                 internal override long GetInt64 (int index)
816                 {
817                         return Convert.ToInt64 (_values[index]);
818                 }
819         }
820
821         class ObjectDataContainer : DataContainer {
822                 object [] _values;
823
824                 protected override object GetValue (int index)
825                 {
826                         return _values [index];
827                 }
828
829                 protected override void ZeroOut (int index)
830                 {
831                         _values [index] = null;
832                 }
833
834                 protected override void SetValue (int index, object value)
835                 {
836                         _values [index] = value;
837                 }
838
839                 protected override void SetValueFromSafeDataRecord (int index, ISafeDataRecord record, int field)
840                 {
841                         _values [index] = record.GetValue (field);
842                 }
843
844                 protected override void DoCopyValue (DataContainer from, int from_index, int to_index)
845                 {
846                         _values [to_index] = ((ObjectDataContainer) from)._values [from_index];
847                 }
848
849                 protected override int DoCompareValues (int index1, int index2)
850                 {
851                         object obj1 = _values [index1];
852                         object obj2 = _values [index2];
853
854                         if (obj1 == obj2)
855                                 return 0;
856
857                         if (obj1 is IComparable) {
858                                 try {
859                                         return ((IComparable)obj1).CompareTo (obj2);
860                                 } catch {
861                                         if (obj2 is IComparable) {
862                                                 obj2 = Convert.ChangeType (obj2, Type.GetTypeCode (obj1.GetType ()));
863                                                 return ((IComparable)obj1).CompareTo (obj2);
864                                         }
865                                 }
866                         }
867
868                         return String.Compare (obj1.ToString (), obj2.ToString ());
869                 }
870
871                 protected override void Resize (int size)
872                 {
873                         if (_values == null) {
874                                 _values = new object [size];
875                                 return;
876                         }
877
878                         object[] tmp = new object [size];
879                         Array.Copy (_values, 0, tmp, 0, _values.Length);
880                         _values = tmp;
881                 }
882
883                 internal override long GetInt64 (int index)
884                 {
885                         return Convert.ToInt64 (_values [index]);
886                 }
887         }
888
889         sealed class DateTimeDataContainer : ObjectDataContainer {
890                 protected override void SetValueFromSafeDataRecord (int index, ISafeDataRecord record, int field)
891                 {
892                         base.SetValue (index, record.GetDateTimeSafe (field));
893                 }
894
895                 protected override void SetValue (int index, object value)
896                 {
897                         base.SetValue (index, Convert.ToDateTime (value));
898                 }
899         }
900
901         sealed class DecimalDataContainer : ObjectDataContainer {
902                 protected override void SetValueFromSafeDataRecord (int index, ISafeDataRecord record, int field)
903                 {
904                         base.SetValue (index, record.GetDecimalSafe (field));
905                 }
906
907                 protected override void SetValue (int index, object value)
908                 {
909                         base.SetValue (index, Convert.ToDecimal (value));
910                 }
911         }
912
913         sealed class StringDataContainer : ObjectDataContainer {
914                 private void SetValue (int index, string value)
915                 {
916                         if (value != null && Column.MaxLength >= 0 && Column.MaxLength < value.Length)
917                                 throw new ArgumentException ("Cannot set column '" + Column.ColumnName + "' to '" + value + "'. The value violates the MaxLength limit of this column.");
918                         base.SetValue (index, value);
919                 }
920
921                 protected override void SetValue (int index, object value)
922                 {
923                         SetValue (index, value is string ? (string) value : Convert.ToString (value));
924                 }
925
926                 protected override void SetValueFromSafeDataRecord (int index, ISafeDataRecord record, int field)
927                 {
928                         SetValue (index, record.GetStringSafe (field));
929                 }
930
931                 protected override int DoCompareValues (int index1, int index2)
932                 {
933                         DataTable table = Column.Table;
934                         return String.Compare ((string) this [index1], (string) this [index2], !table.CaseSensitive, table.Locale);
935                 }
936         }
937 }