Fixed API: added missing attribute System.Serializable
[mono.git] / mcs / class / Microsoft.VisualBasic / Microsoft.VisualBasic / Conversion.cs
1 //
2 // Conversion.cs
3 //
4 // Author:
5 //   Chris J Breisch (cjbreisch@altavista.net) 
6 //
7 // (C) 2002 Chris J Breisch
8 //
9
10 //
11 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32
33 using System;
34 using System.Text.RegularExpressions;
35
36 namespace Microsoft.VisualBasic {
37         [Microsoft.VisualBasic.CompilerServices.StandardModuleAttribute] 
38         sealed public class Conversion {
39                 ///
40                 /// <summary>
41                 ///             Collection : The BASIC Collection Object
42                 ///     </summary>
43                 ///
44                 ///     <remarks>
45                 ///     </remarks>
46                 private Conversion ()
47                 {
48                         //Nothing to do, nobody should see this constructor
49                 }
50
51                 // Declarations
52                 private static readonly char[] _HexDigits = {
53                         '0', '1', '2', '3', '4', '5', '6', '7', 
54                         '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
55                 };
56                 private static readonly char[] _OctDigits = {
57                         '0', '1', '2', '3', '4', '5', '6', '7'
58                 };
59                 private static readonly long[] _Maxes = {
60                         32767, 2147483647, 9223372036854775807
61                 };
62                 private enum SizeIndexes {
63                         Int16 = 0,
64                         Int32 = 1,
65                         Int64 = 2
66                 };
67
68                 // Constructors
69                 // Properties
70                 // Methods
71
72                 public static string ErrorToString () { 
73                         return Information.Err().Description;
74                 }
75
76                 public static string ErrorToString (System.Int32 ErrorNumber) {
77                         if(ErrorNumber >= 65535)
78                                 throw new ArgumentException(VBUtils.GetResourceString("MaxErrNumber"));
79                         if(ErrorNumber == 0)
80                                 return Information.Err().Description;
81
82                         String errStr = VBUtils.GetResourceString(ErrorNumber);
83                 
84                         if (errStr == null)
85                                 errStr = VBUtils.GetResourceString(95);
86                 
87                         return errStr;
88                 }
89
90                 // Return whether d is +/- Could do this with a macro, 
91                 // but this is cleaner
92                 private static int Sign(double d) { return d > 0 ? 1 : -1;}
93
94                 // try to cast an Object to a string...used in several places
95                 private static string CastToString (System.Object Expression) {
96                         try {
97                                 return Expression.ToString();
98                         }
99                         catch {
100                                 throw new InvalidCastException();
101                         }
102                 }
103                 
104                 // Fix on Integer types doesn't do anything
105                 public static short Fix (short Number) { return Number; }
106                 public static int Fix (int Number) { return Number; }
107                 public static long Fix (long Number) { return Number; }
108
109                 // Fix on other numberic types = Sign(Number) * Int(Abs(Number))
110                 public static double Fix (double Number) { 
111                         return Sign(Number) * Int (Math.Abs (Number)); 
112                 }
113                 public static float Fix (float Number) { 
114                         return Sign(Number) * Int (Math.Abs (Number)); 
115                 }
116                 public static decimal Fix (decimal Number) { 
117                         return Sign((double)Number) * Int (Math.Abs (Number)); 
118                 }
119
120                 // Fix on an Object type is trickier
121                 // first we have to cast it to the right type
122                 public static System.Object Fix (System.Object Number)
123                 {
124                         // always start out by throwing an exception 
125                         // if Number is null
126                         if (Number == null) {
127                                 throw new ArgumentNullException ("Number", 
128                                         "Value cannot be null");
129                         }
130
131                         TypeCode TC = Type.GetTypeCode (Number.GetType ());
132
133                         // switch on TypeCode and call appropriate Fix method
134                         switch (TC) {
135                                 case TypeCode.Decimal:
136                                         return Fix (Convert.ToDecimal (Number));
137                                 case TypeCode.Double:
138                                         return Fix (Convert.ToDouble (Number));
139                                 case TypeCode.Single:
140                                         return Fix (Convert.ToSingle (Number));
141                                 case TypeCode.String:
142                                         return Fix (Double.Parse (
143                                                 CastToString (Number)));
144
145                                 // for integer types, don't need to do anything
146                                 case TypeCode.Byte:
147                                 case TypeCode.Int16:
148                                 case TypeCode.Int32:
149                                 case TypeCode.Int64:
150                                 case TypeCode.SByte:
151                                 case TypeCode.UInt16:
152                                 case TypeCode.UInt32:
153                                 case TypeCode.UInt64:
154                                         return Number;
155
156                                 // spec defines Empty as returning 0
157                                 case TypeCode.Empty:
158                                         return 0;
159
160                                 // we can't convert these types
161                                 case TypeCode.Boolean:
162                                 case TypeCode.Char:
163                                 case TypeCode.DateTime:
164                                 case TypeCode.DBNull:
165                                 case TypeCode.Object:
166                                 default:
167                                         throw new ArgumentException (
168                                                 "Type of argument 'Number' is '"
169                                                 + Number.GetType().FullName + 
170                                                 "', which is not numeric.");
171                         }
172                 }
173
174                 // Int on Integer types doesn't do anything
175                 public static short Int (short Number) { return Number; }
176                 public static int Int (int Number) { return Number; }
177                 public static long Int (long Number) { return Number; }
178
179                 // Int on other numberic types is same thing as "Floor"
180                 public static double Int (double Number) { 
181                         return (double) Math.Floor(Number); 
182                 }
183                 public static float Int (float Number) {
184                         return (float) Math.Floor(Number); 
185                 }
186                 public static decimal Int (decimal Number) {
187                         return Decimal.Floor(Number); 
188                 }
189
190                 // doing an Int on an Object is trickier
191                 // first we have to cast to the correct type
192                 public static System.Object Int (System.Object Number) {
193                         // always start out by throwing an exception 
194                         // if Number is null
195                         if (Number == null) {
196                                 throw new ArgumentNullException("Number", 
197                                         "Value cannot be null");
198                         }
199
200                         TypeCode TC = Type.GetTypeCode (Number.GetType ());
201
202                         // switch on TypeCode and call appropriate Int method
203                         switch (TC) {
204                                 case TypeCode.Decimal:
205                                         return Int (Convert.ToDecimal (Number));
206                                 case TypeCode.Double:
207                                         return Int (Convert.ToDouble (Number));
208                                 case TypeCode.Single:
209                                         return Int (Convert.ToSingle (Number));
210                                 case TypeCode.String:
211                                         return Int (Double.Parse (
212                                         CastToString(Number)));
213
214                                 // Int on integer types does nothing
215                                 case TypeCode.Byte:
216                                 case TypeCode.Int16:
217                                 case TypeCode.Int32:
218                                 case TypeCode.Int64:
219                                 case TypeCode.SByte:
220                                 case TypeCode.UInt16:
221                                 case TypeCode.UInt32:
222                                 case TypeCode.UInt64:
223                                         return Number;
224
225                                 // Spec defines Empty as returning 0
226                                 case TypeCode.Empty:
227                                         return 0;
228
229                                 // otherwise, it's we can't cast to a numeric
230                                 case TypeCode.Boolean:
231                                 case TypeCode.Char:
232                                 case TypeCode.DateTime:
233                                 case TypeCode.DBNull:
234                                 case TypeCode.Object:
235                                 default:
236                                         throw new ArgumentException (
237                                         "Type of argument 'Number' is '" + 
238                                         Number.GetType().FullName + 
239                                         "', which is not numeric.");                    
240                         }
241                 }
242
243                 // we use this internally to get a string 
244                 // representation of a number in a specific base
245                 private static string ToBase (ulong Number, int Length, 
246                         char[] BaseDigits, uint Base) {
247                         int i;
248                         ulong r;
249                         // we use a char array here for performance
250                         char [] c = new Char[Length];
251                         string s = null;
252                         
253                         
254                         for (i = Length - 1; i >= 0; i--) {
255                                 r = Number % Base;
256                                 Number = Number / Base;
257                                 c[i] = BaseDigits[r];
258                                 if (Number == 0) {
259                                         s = new string (c, i, Length - i);
260                                         break;
261                                 }
262                         }
263                         if (s == null) {
264                                 return new string (c);
265                         }
266                         else {
267                                 return s;
268                         }
269                 }
270
271
272                 // convert a number to Hex
273                 // a little bit of magic goes on here with negative #'s
274                 private static string ToHex(long Number, int Digits, 
275                         SizeIndexes Size) {
276                         ulong UNumber;
277
278                         if (Number < 0) {
279                                 // we add maxint of the Number's type 
280                                 // twice and then 2 more...this has the
281                                 // effect of turning it into a ulong 
282                                 // that has the same hex representation
283                                 UNumber = (ulong)((Number + 2) + 
284                                         _Maxes[(int)Size]) + 
285                                         (ulong)_Maxes[(int)Size];
286                         }
287                         else {
288                                 UNumber = (ulong)Number;
289                         }
290                         return ToBase(UNumber, Digits, _HexDigits, 16);
291                 }
292
293                 // call our private function, 
294                 // passing it the size of the item to convert
295                 public static string Hex (short Number) { 
296                         return ToHex(Number, 4, SizeIndexes.Int16); 
297                 }
298                 public static string Hex (byte Number) { 
299                         return ToHex(Number, 2, SizeIndexes.Int16); 
300                 }
301                 public static string Hex (int Number) { 
302                         return ToHex(Number, 8, SizeIndexes.Int32); 
303                 }
304                 public static string Hex (long Number) { 
305                         return ToHex(Number, 16, SizeIndexes.Int64); 
306                 }
307
308                 // Objects are trickier
309                 // first we have to cast to appropriate type
310                 public static System.String Hex (System.Object Number) {
311                         // always start out by throwing an exception 
312                         // if Number is null
313                         long lval;
314                         if (Number == null) {
315                                 throw new ArgumentNullException ("Number", 
316                                         "Value cannot be null");
317                         }
318
319                         TypeCode TC = Type.GetTypeCode (Number.GetType ());
320
321                         switch (TC) {
322                                 // try to parse the string as an Int32, 
323                                 // then an Int64, if that fails
324                                 case TypeCode.String:
325                                         try {
326                                                 return Hex (
327                                                         Int32.Parse (
328                                                         CastToString (Number)));
329                                         }
330                                         catch {
331                                                 return Hex (
332                                                         Int64.Parse (
333                                                         CastToString (Number)));
334                                         }
335
336                                 // for the int types, 
337                                 // just call the normal "Hex" for that type
338                                 case TypeCode.Byte:
339                                         return Hex ((byte)Number);
340                                 case TypeCode.Int16:
341                                         return Hex ((short)Number);
342                                 case TypeCode.Int32:
343                                         return Hex ((int)Number);
344                                 case TypeCode.Int64:
345                                         return Hex ((long)Number);
346
347                                 // empty is defined as returning 0
348                                 case TypeCode.Empty:
349                                         return "0";
350                                 case TypeCode.Single:
351                                         float fval = (float)Number;
352                                         lval = (long) Math.Round(fval);
353                                         if ((lval > Int32.MinValue) && (lval < Int32.MaxValue))
354                                                 return Hex ((int)lval);         
355
356                                         return Hex(lval);
357                                 case TypeCode.Double:
358                                         double dval = (double)Number;
359                                         if (dval > Int64.MaxValue || dval < Int64.MinValue)
360                                                 throw new OverflowException(
361                                                   VBUtils.GetResourceString("Overflow_Int64")); 
362                                         lval = (long) Math.Round(dval);
363                                         if ((lval > Int32.MinValue) && (lval < Int32.MaxValue))
364                                                   return Hex((int)lval);
365
366                                         return Hex(lval);
367                                 
368                                 case TypeCode.Decimal:
369                                         Decimal big = new Decimal(Int64.MaxValue);
370                                         Decimal small = new Decimal(Int64.MinValue);
371                                         Decimal current = (Decimal)Number;
372
373                                         if (current.CompareTo(big) > 0 || 
374                                                 current.CompareTo(small) < 0)
375                                                 throw new OverflowException(
376                                                     VBUtils.GetResourceString("Overflow_Int64"));
377
378                                        lval = Decimal.ToInt64(current);
379                                        if ((lval > Int32.MinValue) && (lval < Int32.MaxValue))
380                                                 return Hex((int)lval);
381
382                                        return Hex(lval);
383                                 // we can't do any of these types
384                                 case TypeCode.Boolean:
385                                 case TypeCode.Char:
386                                 case TypeCode.DBNull:
387                                 case TypeCode.DateTime:
388                                 case TypeCode.Object:
389                                 case TypeCode.SByte:
390                                 case TypeCode.UInt16:
391                                 case TypeCode.UInt32:
392                                 case TypeCode.UInt64:
393                                 default:
394                                         throw new ArgumentException (
395                                         "Type of argument 'Number' is '" + 
396                                         Number.GetType().FullName + 
397                                         "', which is not numeric.");                    
398                         }
399                 }
400                 
401                 // ToOct works just like ToHex, only in Octal.
402                 private static string ToOct(long Number, int Digits, 
403                         SizeIndexes Size) {
404                         ulong UNumber;
405
406                         if (Number < 0) {
407                                 // for neg numbers add the maxint of 
408                                 // the appropriate size twice, and then two more
409                                 // this has the effect of turning it 
410                                 // into a ulong with the same oct representation
411                                 UNumber = (ulong)((Number + 2) + 
412                                         _Maxes[(int)Size]) + 
413                                         (ulong)(_Maxes[(int)Size]);
414                         }
415                         else {
416                                 UNumber = (ulong)Number;
417                         }
418                         return ToBase (UNumber, Digits, _OctDigits, 8);
419                 }
420
421                 // call ToOct with appropriate information
422                 public static string Oct (short Number) { 
423                         return ToOct(Number, 6, SizeIndexes.Int16); 
424                 }
425                 public static string Oct (byte Number) { 
426                         return ToOct(Number, 3, SizeIndexes.Int16); 
427                 }
428                 public static string Oct (int Number) { 
429                         return ToOct(Number, 11, SizeIndexes.Int32); 
430                 }
431                 public static string Oct (long Number) { 
432                         return ToOct(Number, 22, SizeIndexes.Int64); 
433                 }
434
435                 // Objects are always trickier
436                 // first need to cast to appropriate type
437                 public static string Oct (System.Object Number) {
438                         // first, always throw an exception if Number is null
439                         if (Number == null) {
440                                 throw new ArgumentNullException("Number", 
441                                         "Value cannot be null");
442                         }
443                         long lval;
444                         TypeCode TC = Type.GetTypeCode (Number.GetType ());
445
446                         switch (TC) {
447                                 // try to parse a string as an Int32 
448                                 // and then an Int64
449                                 case TypeCode.String:
450                                         try {
451                                                 return Oct (
452                                                         Int32.Parse (
453                                                         CastToString (Number)));
454                                         }
455                                         catch {
456                                                 return Oct (
457                                                         Int64.Parse (
458                                                         CastToString (Number)));
459                                         }
460
461                                 // integer types just call the appropriate "Oct"
462                                 case TypeCode.Byte:
463                                         return Oct ((byte)Number);
464                                 case TypeCode.Int16:
465                                         return Oct ((short)Number);
466                                 case TypeCode.Int32:
467                                         return Oct ((int)Number);
468                                 case TypeCode.Int64:
469                                         return Oct ((long)Number);
470                                 case TypeCode.Single:
471                                         float fval = (float)Number;
472                                         lval = (long) Math.Round(fval);
473                                         if ((lval > Int32.MinValue) && (lval < Int32.MaxValue))
474                                                 return Oct((int)lval);
475
476                                         return Oct(lval);       
477                                 case TypeCode.Double:
478                                          double dval = (double)Number;
479                                          if (dval > Int64.MaxValue || dval < Int64.MinValue)
480                                                 throw new OverflowException(
481                                                     VBUtils.GetResourceString("Overflow_Int64"));
482
483                                          lval = (long) Math.Round(dval);
484                                          if ((lval > Int32.MinValue) && (lval < Int32.MaxValue))
485                                                 return Oct((int)lval);
486
487                                         return Oct(lval);
488                                 case TypeCode.Decimal:
489                                         Decimal big = new Decimal(Int64.MaxValue);
490                                         Decimal small = new Decimal(Int64.MinValue);
491                                         Decimal current = (Decimal) Number;
492
493                                         if ((current.CompareTo(big) > 0) || 
494                                                 (current.CompareTo(small) < 0))
495                                                 throw new OverflowException(
496                                                     VBUtils.GetResourceString("Overflow_Int64"));
497             
498                                         lval = Decimal.ToInt64(current);
499                                         if ((lval > Int32.MinValue) && (lval < Int32.MaxValue))
500                                                 return Oct((int)lval);
501
502                                         return Oct(lval);
503                                 // Empty is defined as returning 0
504                                 case TypeCode.Empty:
505                                         return "0";
506
507                                 // We can't convert these to Octal
508                                 case TypeCode.Boolean:
509                                 case TypeCode.Char:
510                                 case TypeCode.DBNull:
511                                 case TypeCode.DateTime:
512                                 case TypeCode.Object:
513                                 case TypeCode.SByte:
514                                 case TypeCode.UInt16:
515                                 case TypeCode.UInt32:
516                                 case TypeCode.UInt64:
517                                 default:
518                                         throw new ArgumentException (
519                                         "Type of argument 'Number' is '" + 
520                                         Number.GetType().FullName + 
521                                         "', which is not numeric.");                    
522                         }
523                 }
524
525                 // Str is pretty easy now that we have a language 
526                 // with a ToString method()
527                 public static string Str (System.Object Number) {
528
529                         // check for null as always and throw an exception
530                         if (Number == null) {
531                                 throw new ArgumentNullException("Number");
532                         }
533
534                         switch (Type.GetTypeCode (Number.GetType ())) {
535                                 // for unsigned types, just call ToString
536                                 case TypeCode.Byte:
537                                 case TypeCode.UInt16:
538                                 case TypeCode.UInt32:
539                                 case TypeCode.UInt64:
540                                         return Number.ToString();
541
542                                 // for signed types, we have to leave a 
543                                 // space for the missing + sign
544                                 case TypeCode.Decimal:
545                                         return ((decimal)Number > 0 ? " " : "")
546                                                 + Number.ToString();
547                                 case TypeCode.Double:
548                                         return ((double)Number > 0 ? " " : "") 
549                                                 + Number.ToString();
550                                 case TypeCode.Int16:
551                                         return ((short)Number > 0 ? " " : "") 
552                                                 + Number.ToString();
553                                 case TypeCode.Int32:
554                                         return ((int)Number > 0 ? " " : "") 
555                                                 + Number.ToString();
556                                 case TypeCode.Int64:
557                                         return ((long)Number > 0 ? " " : "") 
558                                                 + Number.ToString();
559                                 case TypeCode.SByte:
560                                         return ((sbyte)Number > 0 ? " " : "") 
561                                                 + Number.ToString();
562                                 case TypeCode.Single:
563                                         return ((float)Number > 0 ? " " : "") 
564                                                 + Number.ToString();
565
566                                 // can't cast anything else to a Number
567                                 default:
568                                         throw new InvalidCastException(
569                                         "Argument 'Number' cannot be converted to a numeric value.");                   
570                         }
571                 }
572
573                 // The Val function is pretty bizarre
574                 // Val ("&HFF") = 255
575                 // Val ("&O377") = 255
576                 // Val ("1234 Any Street") = 1234
577                 // Val ("     12   45    .   90  7   E    +   0 0 2  ") = 1245.907e+002 = 124590.7
578                 public static double Val (string InputStr) {
579                         int i;
580                         int Base; 
581                         int NumChars = 0;
582                         char c;
583                         int Length = InputStr.Length;
584                         char[] Number = new char[Length];
585                         bool FoundRadixPrefix = false;
586                         Regex NumberReg;
587                         Match NumberMatch;
588                         
589                         Base = 10;
590                         Number[0] = '\0';
591
592                         // go through string
593                         for (i = 0; i < Length; i++) {
594                                 c = InputStr[i];
595
596                                 // look for Radix prefix "&"
597                                 if (i == 0 && c == '&') {
598                                         FoundRadixPrefix = true;
599                                 }
600                         
601                                 // look for an H or O following the prefix
602                                 else if (FoundRadixPrefix && i == 1 && 
603                                         (char.ToLower(c) == 'h' || 
604                                         char.ToLower(c) == 'o')) {
605                                         if (c == 'H') {
606                                                 Base = 16;
607                                         }
608                                         else {
609                                                 Base = 8;
610                                         }
611                                 }
612
613                                 // if we didn't find a radix prefix, 
614                                 // ignore whitespace
615                                 else if (char.IsWhiteSpace(c) && (Base == 10)) {
616                                         continue;
617                                 }
618
619                                 // mash what's left together
620                                 else {
621                                         Number[NumChars++] = c;
622                                 }
623                         }
624                         
625                         // now we have a string to parse
626                         switch (Base) {
627                                 // FIXME : for Octal and Hex, 
628                                 // Regex is probably overkill
629                                 // Even for base 10, it might be faster 
630                                 // to write our own parser
631                                 case 8:
632                                         NumberReg = new Regex ("^[0-7]*");
633                                         NumberMatch = NumberReg.Match (
634                                         new string(Number, 0, NumChars));
635                                         break;
636                                 case 16:
637                                         NumberReg = new Regex ("^[0-9a-f]*", 
638                                                 RegexOptions.IgnoreCase);
639                                         NumberMatch = NumberReg.Match (
640                                         new string(Number, 0, NumChars));
641                                         break;
642                                 case 10:
643                                 default:
644                                         NumberReg = new Regex (
645                                         "^[+-]?\\d*\\.?\\d*(e[+-]?\\d*)?", 
646                                         RegexOptions.IgnoreCase);
647                                         NumberMatch = NumberReg.Match (
648                                         new string(Number, 0, NumChars));
649                                         break;
650                                 
651
652                         }
653                         
654                         // we found a match, try to convert it
655                         if (NumberMatch.Success) {
656                                 try {
657                                         if(NumberMatch.Length == 0)
658                                                 return (double)0;
659
660                                         switch (Base) {
661                                                 case 10:
662                                                         return 
663                                                         Convert.ToDouble (
664                                                         NumberMatch.Value);
665                                                 case 8:
666                                                 case 16:
667                                                         return (double)
668                                                         Convert.ToInt64 (
669                                                         NumberMatch.Value, 
670                                                                 Base);
671                                                 default:
672                                                         return (double)0;
673                                         }
674                                 } 
675                                 catch {
676                                         throw new OverflowException();
677                                 }
678                         }
679                         else {
680                                 return (double)0;
681                         }
682                 }
683
684                 // Val on a char type is pretty simple  '9' = 9, 'a' = exception
685                 public static int Val (char Expression) {
686                         if (char.IsDigit(Expression)) {
687                                 return Expression - '0';
688                         } 
689                         else {
690                                 throw new ArgumentException();
691                         }
692                 }
693
694                 // if it's an object, and we can't convert 
695                 // it to a string, it's an exception
696                 public static double Val (System.Object Expression) {
697                         // always check for null first
698                         if (Expression == null) {
699                                 throw new ArgumentNullException ("Expression", 
700                                         "Value cannot be null");
701                         }
702                 
703                         try {
704                                 return Val (CastToString (Expression)); 
705                         } 
706                         catch {
707                                 
708                                 throw new ArgumentException(
709                                 "Type of argument 'Expression' is '" + 
710                                 Expression.GetType().FullName + 
711                                 "', which can nt be converted to numeric.");                    
712                         }
713                 }
714                 // Events
715         }
716 }