New test.
[mono.git] / mcs / class / corlib / System / Delegate.cs
index 3dc4fe78ec02e8b6d4d633f2f7c2521ef24a05c9..733eac9a4d3f132eab175fecdeed571364b4145f 100644 (file)
@@ -33,6 +33,7 @@
 //
 
 using System.Reflection;
+using System.Runtime.Remoting;
 using System.Runtime.Serialization;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
@@ -45,13 +46,9 @@ namespace System
                public string method_name;
        }
 
-#if NET_1_1
        [ClassInterface (ClassInterfaceType.AutoDual)]
-#endif
-#if NET_2_0
        [System.Runtime.InteropServices.ComVisible (true)]
        [Serializable]
-#endif
        public abstract class Delegate : ICloneable, ISerializable
        {
                #region Sync with object-internals.h
@@ -122,49 +119,39 @@ namespace System
                //
 
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               internal static extern Delegate CreateDelegate_internal (Type type, object target, MethodInfo info);
+               internal static extern Delegate CreateDelegate_internal (Type type, object target, MethodInfo info, bool throwOnBindFailure);
 
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
                internal extern void SetMulticastInvoke ();
 
-#if NET_2_0
                private static bool arg_type_match (Type delArgType, Type argType) {
                        bool match = delArgType == argType;
 
                        // Delegate contravariance
                        if (!match) {
-                               if (!delArgType.IsValueType && (delArgType != typeof (ValueType)) && (argType.IsAssignableFrom (delArgType)))
+                               if (!argType.IsValueType && argType.IsAssignableFrom (delArgType))
                                        match = true;
                        }
 
                        return match;
                }
-#endif         
 
                private static bool return_type_match (Type delReturnType, Type returnType) {
                        bool returnMatch = returnType == delReturnType;
 
-#if NET_2_0
                        if (!returnMatch) {
                                // Delegate covariance
-                               if (!delReturnType.IsValueType && (delReturnType != typeof (ValueType)) && (delReturnType.IsAssignableFrom (returnType)))
+                               if (!returnType.IsValueType && delReturnType.IsAssignableFrom (returnType))
                                        returnMatch = true;
                        }
-#endif
 
                        return returnMatch;
                }
 
-#if NET_2_0
                public static Delegate CreateDelegate (Type type, object firstArgument, MethodInfo method, bool throwOnBindFailure)
-#else
-               internal static Delegate CreateDelegate (Type type, object target, MethodInfo method, bool throwOnBindFailure)
-#endif
                {
-#if NET_2_0
                        // The name of the parameter changed in 2.0
                        object target = firstArgument;
-#endif
 
                        if (type == null)
                                throw new ArgumentNullException ("type");
@@ -174,14 +161,6 @@ namespace System
 
                        if (!type.IsSubclassOf (typeof (MulticastDelegate)))
                                throw new ArgumentException ("type is not a subclass of Multicastdelegate");
-#if !NET_2_0
-                       if ((target == null) && !method.IsStatic) {
-                               if (throwOnBindFailure)
-                                       throw new ArgumentException ("The method should be static.", "method");
-                               else
-                                       return null;
-                       }
-#endif
 
                        MethodInfo invoke = type.GetMethod ("Invoke");
 
@@ -191,8 +170,6 @@ namespace System
                                else
                                        return null;
 
-                       // FIXME: Figure out how net 1.1 works
-#if NET_2_0
                        ParameterInfo[] delargs = invoke.GetParameters ();
                        ParameterInfo[] args = method.GetParameters ();
 
@@ -213,8 +190,13 @@ namespace System
                                        // as the 'this' argument to the method.
                                        //
                                        argLengthMatch = (args.Length + 1 == delargs.Length);
-                               else
+                               else {
                                        argLengthMatch = (args.Length == delargs.Length);
+
+                                       if (!argLengthMatch)
+                                               // closed over a null reference
+                                               argLengthMatch = args.Length == delargs.Length + 1;
+                               }
                        }
                        if (!argLengthMatch)
                                if (throwOnBindFailure)
@@ -240,9 +222,16 @@ namespace System
                                        for (int i = 0; i < args.Length; i++)
                                                argsMatch &= arg_type_match (delargs [i + 1].ParameterType, args [i].ParameterType);
                                } else {
-                                       argsMatch = true;
-                                       for (int i = 0; i < args.Length; i++)
-                                               argsMatch &= arg_type_match (delargs [i].ParameterType, args [i].ParameterType);
+                                       if (delargs.Length + 1 == args.Length) {
+                                               // closed over a null reference
+                                               argsMatch = !args [0].ParameterType.IsValueType;
+                                               for (int i = 0; i < delargs.Length; i++)
+                                                       argsMatch &= arg_type_match (delargs [i].ParameterType, args [i + 1].ParameterType);
+                                       } else {
+                                               argsMatch = true;
+                                               for (int i = 0; i < args.Length; i++)
+                                                       argsMatch &= arg_type_match (delargs [i].ParameterType, args [i].ParameterType);
+                                       }
                                }
                        }
 
@@ -251,29 +240,18 @@ namespace System
                                        throw new ArgumentException ("method arguments are incompatible");
                                else
                                        return null;
-#endif
 
-                       Delegate d = CreateDelegate_internal (type, target, method);
-                       d.original_method_info = method;
+                       Delegate d = CreateDelegate_internal (type, target, method, throwOnBindFailure);
+                       if (d != null)
+                               d.original_method_info = method;
                        return d;
                }
 
-#if NET_2_0
                public static Delegate CreateDelegate (Type type, object firstArgument, MethodInfo method) {
                        return CreateDelegate (type, firstArgument, method, true);
                }
-#else
-               internal static Delegate CreateDelegate (Type type, object target, MethodInfo method) {
-                       return CreateDelegate (type, target, method, true);
-               }
-#endif
 
-#if NET_2_0
-               public
-#else
-               internal
-#endif
-               static Delegate CreateDelegate (Type type, MethodInfo method, bool throwOnBindFailure)
+               public static Delegate CreateDelegate (Type type, MethodInfo method, bool throwOnBindFailure)
                {
                        return CreateDelegate (type, null, method, throwOnBindFailure);
                }
@@ -343,12 +321,7 @@ namespace System
                        return info;
                }
 
-#if NET_2_0
-               public 
-#else
-               internal
-#endif
-               static Delegate CreateDelegate (Type type, Type target, string method, bool ignoreCase, bool throwOnBindFailure)
+               public static Delegate CreateDelegate (Type type, Type target, string method, bool ignoreCase, bool throwOnBindFailure)
                {
                        if (target == null)
                                throw new ArgumentNullException ("target");
@@ -358,25 +331,18 @@ namespace System
                        if (info == null)
                                return null;
 
-                       return CreateDelegate_internal (type, null, info);
+                       return CreateDelegate_internal (type, null, info, throwOnBindFailure);
                }
 
                public static Delegate CreateDelegate (Type type, Type target, string method) {
                        return CreateDelegate (type, target, method, false, true);
                }
 
-#if NET_2_0
                public static Delegate CreateDelegate (Type type, Type target, string method, bool ignoreCase) {
                        return CreateDelegate (type, target, method, ignoreCase, true);
                }
-#endif
 
-#if NET_2_0
-               public
-#else
-               internal
-#endif
-               static Delegate CreateDelegate (Type type, object target, string method, bool ignoreCase, bool throwOnBindFailure)
+               public static Delegate CreateDelegate (Type type, object target, string method, bool ignoreCase, bool throwOnBindFailure)
                {
                        if (target == null)
                                throw new ArgumentNullException ("target");
@@ -386,18 +352,14 @@ namespace System
                        if (info == null)
                                return null;
 
-                       return CreateDelegate_internal (type, target, info);
+                       return CreateDelegate_internal (type, target, info, throwOnBindFailure);
                }
 
                public static Delegate CreateDelegate (Type type, object target, string method, bool ignoreCase) {
                        return CreateDelegate (type, target, method, ignoreCase, true);
                }
 
-#if NET_2_0
                public object DynamicInvoke (params object[] args)
-#else
-               public object DynamicInvoke (object[] args)
-#endif
                {
                        return DynamicInvokeImpl (args);
                }
@@ -412,7 +374,6 @@ namespace System
                                method_info = m_target.GetType ().GetMethod (data.method_name, mtypes);
                        }
 
-#if NET_2_0
                        if ((m_target != null) && Method.IsStatic) {
                                // The delegate is bound to m_target
                                if (args != null) {
@@ -425,7 +386,6 @@ namespace System
                                }
                                return Method.Invoke (null, args);
                        }
-#endif
 
                        return Method.Invoke (m_target, args);
                }
@@ -459,8 +419,7 @@ namespace System
 
                public override int GetHashCode ()
                {
-                       // FIXME: Sync with Equals above
-                       return (int)method_ptr;
+                       return method.GetHashCode () ^ (m_target != null ? m_target.GetHashCode () : 0);
                }
 
                protected virtual MethodInfo GetMethodImpl ()
@@ -503,12 +462,8 @@ namespace System
                ///   Returns a new MulticastDelegate holding the
                ///   concatenated invocation lists of an Array of MulticastDelegates
                /// </symmary>
-#if NET_2_0
                [System.Runtime.InteropServices.ComVisible (true)]
                public static Delegate Combine (params Delegate[] delegates)
-#else
-               public static Delegate Combine (Delegate[] delegates)
-#endif
                {
                        if (delegates == null)
                                return null;
@@ -541,7 +496,7 @@ namespace System
 
                        return this;
                }
-#if NET_1_1
+
                public static Delegate RemoveAll (Delegate source, Delegate value)
                {
                        Delegate tmp = source;
@@ -550,7 +505,7 @@ namespace System
 
                        return tmp;
                }
-#endif
+
                public static bool operator == (Delegate d1, Delegate d2)
                {
                        if ((object)d1 == null) {
@@ -567,5 +522,10 @@ namespace System
                {
                        return !(d1 == d2);
                }
+
+               internal bool IsTransparentProxy ()
+               {
+                       return RemotingServices.IsTransparentProxy (m_target);
+               }
        }
 }