Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Constructor base keyword

Tags:

c#

prism-4

I was poking into Microsoft.Practices.Prism assembly using reflector and came across the following definition for the constructor of DelagateCommand:

public DelegateCommand(Action executeMethod, Func<bool> canExecuteMethod) 
    : base(action, func)
{
    Action<object> action = null;
    Func<object, bool> func = null;
    if (action == null)
    {
        action = o => executeMethod();
    }
    if (func == null)
    {
        func = o => canExecuteMethod();
    }
    if ((executeMethod == null) || (canExecuteMethod == null))
    {
        throw new ArgumentNullException(
            "executeMethod", 
            Resources.DelegateCommandDelegatesCannotBeNull);
    }
}

This code does not compile since : base(action, func) points to the first two variables in the ctor.

Is it possible to replicate this kind of behavior? perhaps by the use of anon methods?

Thank you in advance for your input.

Reflector IL for this method:

.method public hidebysig specialname rtspecialname instance void .ctor(class [mscorlib]System.Action executeMethod, class [mscorlib]System.Func`1<bool> canExecuteMethod) cil managed
{
    .maxstack 5
    .locals init (
        [0] class [mscorlib]System.Action`1<object> action,
        [1] class [mscorlib]System.Func`2<object, bool> func,
        [2] class Microsoft.Practices.Prism.Commands.DelegateCommand/<>c__DisplayClass6 class2)
    L_0000: ldnull 
    L_0001: stloc.0 
    L_0002: ldnull 
    L_0003: stloc.1 
    L_0004: newobj instance void Microsoft.Practices.Prism.Commands.DelegateCommand/<>c__DisplayClass6::.ctor()
    L_0009: stloc.2 
    L_000a: ldloc.2 
    L_000b: ldarg.1 
    L_000c: stfld class [mscorlib]System.Action Microsoft.Practices.Prism.Commands.DelegateCommand/<>c__DisplayClass6::executeMethod
    L_0011: ldloc.2 
    L_0012: ldarg.2 
    L_0013: stfld class [mscorlib]System.Func`1<bool> Microsoft.Practices.Prism.Commands.DelegateCommand/<>c__DisplayClass6::canExecuteMethod
    L_0018: ldarg.0 
    L_0019: ldloc.0 
    L_001a: brtrue.s L_0029
    L_001c: ldloc.2 
    L_001d: ldftn instance void Microsoft.Practices.Prism.Commands.DelegateCommand/<>c__DisplayClass6::<.ctor>b__2(object)
    L_0023: newobj instance void [mscorlib]System.Action`1<object>::.ctor(object, native int)
    L_0028: stloc.0 
    L_0029: ldloc.0 
    L_002a: ldloc.1 
    L_002b: brtrue.s L_003a
    L_002d: ldloc.2 
    L_002e: ldftn instance bool Microsoft.Practices.Prism.Commands.DelegateCommand/<>c__DisplayClass6::<.ctor>b__3(object)
    L_0034: newobj instance void [mscorlib]System.Func`2<object, bool>::.ctor(object, native int)
    L_0039: stloc.1 
    L_003a: ldloc.1 
    L_003b: call instance void Microsoft.Practices.Prism.Commands.DelegateCommandBase::.ctor(class [mscorlib]System.Action`1<object>, class [mscorlib]System.Func`2<object, bool>)
    L_0040: ldloc.2 
    L_0041: ldfld class [mscorlib]System.Action Microsoft.Practices.Prism.Commands.DelegateCommand/<>c__DisplayClass6::executeMethod
    L_0046: brfalse.s L_0050
    L_0048: ldloc.2 
    L_0049: ldfld class [mscorlib]System.Func`1<bool> Microsoft.Practices.Prism.Commands.DelegateCommand/<>c__DisplayClass6::canExecuteMethod
    L_004e: brtrue.s L_0060
    L_0050: ldstr "executeMethod"
    L_0055: call string Microsoft.Practices.Prism.Properties.Resources::get_DelegateCommandDelegatesCannotBeNull()
    L_005a: newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string, string)
    L_005f: throw 
    L_0060: ret 
}

Also after looking into the actual source code at codeplex the method definition is as follows:

 public DelegateCommand(Action<T> executeMethod, Func<T, bool> canExecuteMethod)
            : base((o) => executeMethod((T)o), (o) => canExecuteMethod((T)o))
        {
            if (executeMethod == null || canExecuteMethod == null)
                throw new ArgumentNullException("executeMethod", Resources.DelegateCommandDelegatesCannotBeNull);

#if !WINDOWS_PHONE
            Type genericType = typeof(T);

            // DelegateCommand allows object or Nullable<>.  
            // note: Nullable<> is a struct so we cannot use a class constraint.
            if (genericType.IsValueType)
            {
                if ((!genericType.IsGenericType) || (!typeof(Nullable<>).IsAssignableFrom(genericType.GetGenericTypeDefinition())))
                {
                    throw new InvalidCastException(Resources.DelegateCommandInvalidGenericPayloadType);
                }
            }
#endif
        }
like image 720
Ioannis Kappas Avatar asked Apr 13 '12 10:04

Ioannis Kappas


1 Answers

I think this is probably just a reflector bug, trying to represent the way that the backing delegate for lambdas are cached. The real code is most likely:

: base(o => executeMethod(), o => canExecuteMethod())

Do you have the IL to hand?


Edit: Hmmm... I can't repro that. There are two other options, though: in both C++ and IL you can do pretty much anything. That code looks... funky, though.

like image 186
Marc Gravell Avatar answered Sep 22 '22 14:09

Marc Gravell