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