2012-04-13 22 views
5

ja grzebie w zespole Microsoft.Practices.Prism użyciu reflektora i natknąłem się następującą definicją dla konstruktora DelagateCommand:C# Konstruktor baza słów kluczowych

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

Ten kod nie kompiluje od : base(action, func) punktów do dwóch pierwszych zmienne w ctor.

Czy można powtórzyć tego rodzaju zachowanie? być może przy pomocy metod anonowych?

Z góry dziękujemy za Twoje dane wejściowe.

Reflektor IL dla tej metody:

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

Również po patrząc na rzeczywistej source code na CodePlex definicja sposób jest następujący:

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 
     } 

Odpowiedz

6

Myślę, że to prawdopodobnie tylko reflektor bug, próbując przedstawić sposób, w jaki delegat wsparcia dla lambdas jest buforowany. Prawdziwy kod jest najprawdopodobniej:

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

Czy masz IL do przekazania?


Edytuj: Hmmm ... Nie mogę tego zaimponować. Istnieją jednak dwie inne opcje: zarówno w C++, jak i IL można zrobić prawie wszystko. Ten kod wygląda na ... modny.

+1

Tak, to jest rzeczywiste wywołanie podstawowe zgodnie ze źródłem (z wyjątkiem źródła ma nadmiarowe nawiasy: P) ... w PrismLibrary \ Desktop \ Prism \ Commands \ DelegateCommand.cs – BoltClock

+0

@ BoltClock'saUnicorn w tym przypadku, mój reflektor musi być inny niż OP - otrzymuję właściwą wydajność ... chyba że jest to bezczelność i sondowanie mojego .pdb –

+0

Jest to oczywiście błąd reflektora, ale ten kod wygląda naprawdę fajnie! –

0

IMHO, to błąd reflektora. Dlaczego nie zaglądasz do kodu źródłowego Prism?

Powiązane problemy