2009-03-14 Miguel de Icaza <miguel@novell.com>
authorMiguel de Icaza <miguel@gnome.org>
Sat, 14 Mar 2009 18:56:43 +0000 (18:56 -0000)
committerMiguel de Icaza <miguel@gnome.org>
Sat, 14 Mar 2009 18:56:43 +0000 (18:56 -0000)
* Convert.cs (ToType): Control whether this internal function will
call an IConvertible.ToType method or not.

Classes and structs implementing IConvertible in mscorlib (the
only callers that can access Convert.ToType) must pass false to
avoid a infinite recursion problem and callers from the public
Convert API must call it with true.

This fixes the regression reported in #485377 that was introduced
by the fix for #481687.

* Int16.cs, UInt64.cs, Double.cs, Enum.cs, SByte.cs, UInt16.cs,
Byte.cs, Decimal.cs, Int32.cs, String.cs, Int64.cs, Char.cs,
Boolean.cs, Single.cs, UInt32.cs: Update the call sites.

svn path=/trunk/mcs/; revision=129367

18 files changed:
mcs/class/corlib/System/Boolean.cs
mcs/class/corlib/System/Byte.cs
mcs/class/corlib/System/ChangeLog
mcs/class/corlib/System/Char.cs
mcs/class/corlib/System/Convert.cs
mcs/class/corlib/System/Decimal.cs
mcs/class/corlib/System/Double.cs
mcs/class/corlib/System/Enum.cs
mcs/class/corlib/System/Int16.cs
mcs/class/corlib/System/Int32.cs
mcs/class/corlib/System/Int64.cs
mcs/class/corlib/System/SByte.cs
mcs/class/corlib/System/Single.cs
mcs/class/corlib/System/String.cs
mcs/class/corlib/System/UInt16.cs
mcs/class/corlib/System/UInt32.cs
mcs/class/corlib/System/UInt64.cs
mcs/class/corlib/Test/System/ConvertTest.cs

index bd3edccf11653b832f23e0140924ffaf35726729..21793eba8f9bdc1285c343ca7e971518d701f1dc 100644 (file)
@@ -230,7 +230,7 @@ namespace System
 
                object IConvertible.ToType (Type type, IFormatProvider provider)
                {
-                       return System.Convert.ToType (m_value, type, provider);
+                       return System.Convert.ToType (m_value, type, provider, false);
                }
 
                bool IConvertible.ToBoolean (IFormatProvider provider)
index 76918b7acd43fe2bc18c0bae89452774dff89560..e85eca6144de4d30b1a2ae22534877251dc458d2 100644 (file)
@@ -170,7 +170,7 @@ namespace System
 
                object IConvertible.ToType (Type type, IFormatProvider provider)
                {
-                       return System.Convert.ToType (m_value, type, provider);
+                       return System.Convert.ToType (m_value, type, provider, false);
                }
 
                bool IConvertible.ToBoolean (IFormatProvider provider)
index 5aee180fb09cfba7778447de2708377f0b2c052d..4eb7d8e6005f7e6753a475aebae9ac80eb856746 100644 (file)
@@ -1,7 +1,24 @@
+2009-03-14  Miguel de Icaza  <miguel@novell.com>
+
+       * Convert.cs (ToType): Control whether this internal function will
+       call an IConvertible.ToType method or not.  
+
+       Classes and structs implementing IConvertible in mscorlib (the
+       only callers that can access Convert.ToType) must pass false to
+       avoid a infinite recursion problem and callers from the public
+       Convert API must call it with true.
+
+       This fixes the regression reported in #485377 that was introduced
+       by the fix for #481687.
+
+       * Int16.cs, UInt64.cs, Double.cs, Enum.cs, SByte.cs, UInt16.cs,
+       Byte.cs, Decimal.cs, Int32.cs, String.cs, Int64.cs, Char.cs,
+       Boolean.cs, Single.cs, UInt32.cs: Update the call sites.
+
 2009-03-07  Gert Driesen  <drieseng@users.sourceforge.net>
 
-       * Convert.cs: Do not throw InvalidCastException if IConvertible.ToType
-       returns null.
+       * Convert.cs: Do not throw InvalidCastException if
+       IConvertible.ToType returns null.
 
 2009-03-06  AndrĂ©s G. Aragoneses  <aaragoneses@novell.com>
 
@@ -13,7 +30,7 @@
        IConvertible.ToType if there are no other possible conversions
        defined. 
 
-       Fixes: #481687
+       Fixes: #481687 
 
 2009-03-06  Rodrigo Kumpera  <rkumpera@novell.com>
 
index 4b4f9b79a3517826c37d4ce970d0ba6999779459..61e34724fdcff556b96421d8d2d9fd8a0b2b08b5 100644 (file)
@@ -536,7 +536,7 @@ namespace System
 
                object IConvertible.ToType (Type type, IFormatProvider provider)
                {
-                       return System.Convert.ToType (m_value, type, provider);
+                       return System.Convert.ToType (m_value, type, provider, false);
                }
 
                bool IConvertible.ToBoolean (IFormatProvider provider)
index 4329219e56d2d625558c6ee345fd870a6f348cf2..2ade4c952fe54064cbc88bd99dd0f87b09026179 100644 (file)
@@ -2471,7 +2471,7 @@ namespace System {
                        else {
                                provider = ci.NumberFormat;
                        }
-                       return ToType (value, conversionType, provider);
+                       return ToType (value, conversionType, provider, true);
                }
                
                public static object ChangeType (object value, TypeCode typeCode)
@@ -2485,20 +2485,20 @@ namespace System {
                        else {
                                provider = ci.NumberFormat;
                        }
-                       return ToType (value, conversionType, provider);
+                       return ToType (value, conversionType, provider, true);
                }
 
                public static object ChangeType (object value, Type conversionType, IFormatProvider provider)
                {
                        if ((value != null) && (conversionType == null))
                                throw new ArgumentNullException ("conversionType");
-                       return ToType (value, conversionType, provider);
+                       return ToType (value, conversionType, provider, true);
                }
                
                public static object ChangeType (object value, TypeCode typeCode, IFormatProvider provider)
                {
                        Type conversionType = conversionTable [(int)typeCode];
-                       return ToType (value, conversionType, provider);
+                       return ToType (value, conversionType, provider, true);
                }
 
                private static bool NotValidBase (int value)
@@ -2825,8 +2825,19 @@ namespace System {
                // it as an object. In place for the core data types to use
                // when implementing IConvertible. Uses hardcoded indexes in 
                // the conversionTypes array, so if modify carefully.
-               internal static object ToType (object value, Type conversionType, 
-                                              IFormatProvider provider) 
+       
+               //
+               // The `try_target_to_type' boolean indicates if the code
+               // should try to call the IConvertible.ToType method if everything
+               // else fails.
+               //
+               // This should be true for invocations from Convert.cs, and
+               // false from the mscorlib types that implement IConvertible that 
+               // all into this internal function.
+               //
+               // This was added to keep the fix for #481687 working and to avoid
+               // the regression that the simple fix introduced (485377)
+               internal static object ToType (object value, Type conversionType, IFormatProvider provider, bool try_target_to_type) 
                {
                        if (value == null) {
                                if ((conversionType != null) && conversionType.IsValueType){
@@ -2906,12 +2917,13 @@ namespace System {
                                else if (conversionType == conversionTable[18]) // 18 TypeCode.String
                                        return (object) convertValue.ToString (provider);
                                else {
-                                       return convertValue.ToType (conversionType, provider);
+                                       if (try_target_to_type)
+                                               return convertValue.ToType (conversionType, provider);
                                }
-                       } else
-                               // Not in the conversion table
-                               throw new InvalidCastException ((Locale.GetText (
-                                       "Value is not a convertible object: " + value.GetType().ToString() + " to " + conversionType.FullName)));
+                       } 
+                       // Not in the conversion table
+                       throw new InvalidCastException ((Locale.GetText (
+                                                                "Value is not a convertible object: " + value.GetType().ToString() + " to " + conversionType.FullName)));
                }
        }
 }
index 42990058777e050b566dfa7f530ec82703e917f0..4522dc2a0dd5df48d06191bef87459ed47dace26 100644 (file)
@@ -1239,7 +1239,7 @@ namespace System
 
                object IConvertible.ToType (Type type, IFormatProvider provider)
                {
-                       return Convert.ToType (this, type, provider);
+                       return Convert.ToType (this, type, provider, false);
                }
 
                bool IConvertible.ToBoolean (IFormatProvider provider)
index 6ecb6314b050188b821d7e72b385490036ef7100..a18e5800aa67def1d912a421c6da98ee1dc1d4ec 100644 (file)
@@ -531,7 +531,7 @@ namespace System {
 
                object IConvertible.ToType (Type type, IFormatProvider provider)
                {
-                       return System.Convert.ToType (m_value, type, provider);
+                       return System.Convert.ToType (m_value, type, provider, false);
                }
 
                bool IConvertible.ToBoolean (IFormatProvider provider)
index 6e206902020a6f9b05172ea41f945f01f87cbfb0..983ceab6107833ce3dc82b2a417bfcae47dc26c0 100644 (file)
@@ -187,7 +187,7 @@ namespace System
 
                object IConvertible.ToType (Type type, IFormatProvider provider)
                {
-                       return Convert.ToType (get_value (), type, provider);
+                       return Convert.ToType (get_value (), type, provider, false);
                }
 
 #if ONLY_1_1
index 178c90bf48eb7f3fed23f1dc040490e5e6c435c9..81b37894fd8b66ba3d13ae784bad114ba8c92ea2 100644 (file)
@@ -330,7 +330,7 @@ namespace System {
 
                object IConvertible.ToType (Type type, IFormatProvider provider)
                {
-                       return System.Convert.ToType (m_value, type, provider);
+                       return System.Convert.ToType (m_value, type, provider, false);
                }
 
 #if ONLY_1_1
index 28f1e7c6969a0fb7932c17c00d589d95edadbc0f..302ffbf9b34c52dbeb43d74e0d8400d87ca3f8b3 100644 (file)
@@ -714,7 +714,7 @@ namespace System {
 
                object IConvertible.ToType (Type type, IFormatProvider provider)
                {
-                       return System.Convert.ToType (m_value, type, provider);
+                       return System.Convert.ToType (m_value, type, provider, false);
                }
 
 #if ONLY_1_1
index 1cb690873278fb3d30024837a1a6f35bc0449b7d..968c50ba5bdd0aeebbb0daf620b8b97c25925c93 100644 (file)
@@ -586,7 +586,7 @@ namespace System {
 
                object IConvertible.ToType (Type type, IFormatProvider provider)
                {
-                       return System.Convert.ToType (m_value, type, provider);
+                       return System.Convert.ToType (m_value, type, provider, false);
                }
 
 #if ONLY_1_1
index ac6bdf32ad2be594cb20b2f9a18ba999c6a631c5..4bf6460fa64dde9a9ace509847dcbb50ae73b7ac 100644 (file)
@@ -326,7 +326,7 @@ namespace System
 
                object IConvertible.ToType (Type type, IFormatProvider provider)
                {
-                       return System.Convert.ToType (m_value, type, provider);
+                       return System.Convert.ToType (m_value, type, provider, false);
                }
 
                ushort IConvertible.ToUInt16 (IFormatProvider provider)
index 4c178ac2603fcbfb54f1c2919e6bdfbc8d2c4235..d1ec9eec56a3cb22ef216533ff082592feabae81 100644 (file)
@@ -322,7 +322,7 @@ namespace System
 
                object IConvertible.ToType (Type type, IFormatProvider provider)
                {
-                       return System.Convert.ToType (m_value, type, provider);
+                       return System.Convert.ToType (m_value, type, provider, false);
                }
 
 #if ONLY_1_1
index b1b1ae56804fa482b099812b85808e25c856dbea..ec10e9e5c54abdb649b5e90cf9ec7d531b5cf798 100644 (file)
@@ -2424,7 +2424,7 @@ namespace System
 
                object IConvertible.ToType (Type type, IFormatProvider provider)
                {
-                       return Convert.ToType (this, type, provider);
+                       return Convert.ToType (this, type, provider, false);
                }
 
 #if ONLY_1_1
index 53f4f360f02aacefdba871f1046a80065494ace8..150ef0e9f34f49e3705f5c4af01e433198662a51 100644 (file)
@@ -218,7 +218,7 @@ namespace System
 
                object IConvertible.ToType (Type type, IFormatProvider provider)
                {
-                       return System.Convert.ToType (m_value, type, provider);
+                       return System.Convert.ToType (m_value, type, provider, false);
                }
 
 #if ONLY_1_1
index 1e68d45633f855abd26934710d947102f10d7be5..26243315892091d14aa4a881f84f84f768fbdbeb 100644 (file)
@@ -540,7 +540,7 @@ namespace System
 
                object IConvertible.ToType (Type type, IFormatProvider provider)
                {
-                       return System.Convert.ToType (m_value, type, provider);
+                       return System.Convert.ToType (m_value, type, provider, false);
                }
 
 #if ONLY_1_1
index 607a4d1370b63049e2ce75ace18fed6d04a4a70b..7d1aababc2e35b1dfb5e18929b93ec7811e3c0a4 100644 (file)
@@ -463,7 +463,7 @@ namespace System
 
                object IConvertible.ToType (Type type, IFormatProvider provider)
                {
-                       return System.Convert.ToType (m_value, type, provider);
+                       return System.Convert.ToType (m_value, type, provider, false);
                }
 
 #if ONLY_1_1
index 4aaf3e7d8b59235aa2b935775cf8ad1242a25d84..8338804b31d2d8849b42850cea4d24b05d093697 100644 (file)
@@ -4613,6 +4613,17 @@ namespace MonoTests.System {
                        AssertNotNull ("#C1", c3);
                        AssertEquals ("#C2", 3, c3);
                }
+
+               // This is a simple and happy struct.
+               struct Foo {
+               }
+               
+               [Test]
+               [ExpectedException (typeof (InvalidCastException))]
+               public void ChangeType_ShouldThrowOnString ()
+               {
+                       Foo f = (Foo) Convert.ChangeType ("this-is-a-string", typeof (Foo));
+               }
        }
 
        public class Image