2012-04-13 1 views
5

Je poussais dans l'assemblage Microsoft.Practices.Prism utilisant réflecteur et suis tombé sur la définition suivante pour le constructeur de DelagateCommand:C# mot-clé de base Constructor

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); 
    } 
} 

Ce code ne compile pas depuis : base(action, func) des points aux deux premiers variables dans le ctor.

Est-il possible de reproduire ce type de comportement? peut-être par l'utilisation de méthodes anon?

Merci d'avance pour votre contribution.

réflecteur IL pour cette méthode:

.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 
} 

également après avoir regardé dans la source code réelle à CodePlex la définition de la méthode est la suivante:

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 
     } 

Répondre

6

Je pense que c'est probablement juste un réflecteur bug, essayant de représenter la façon dont le délégué de sauvegarde de lambdas est mis en cache. Le vrai code est le plus probable:

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

Avez-vous l'IL à portée de main?


Éditer: Hmmm ... Je ne peux pas le repro. Il y a deux autres options, cependant: en C++ et en IL, vous pouvez faire à peu près n'importe quoi. Ce code a l'air ... funky, cependant.

+1

Oui, c'est l'appel de base réel en fonction de la source (sauf la source a des parenthèses redondantes: P) ... dans PrismLibrary \ Desktop \ Prism \ Commands \ DelegateCommand.cs – BoltClock

+0

@ BoltClock'saUnicorn dans ce cas, mon réflecteur ça doit être différent des OP - j'obtiens la bonne sortie ... à moins d'être insolente et de sonder mon .pdb –

+0

C'est clairement un bug de réflecteur mais ce code a l'air vraiment fonctionnel! –

0

IMHO, c'est l'échec du réflecteur. Pourquoi ne pas regarder dans le code source de Prism?