2010-08-18 22 views
7

Bir Eylem (veya bir Func) alan bir yönteme ihtiyacım var, ancak İşlemde karışık sayıda parametre var.C# Eylem ve Func parametresi aşırı yükleri

public void Execute<T>(Action<T> action, T param) { 
    // TODO: Implement something like: 
    // Execute(action, param, null); 
} 

public void Execute<T1,T2>(Action<T1,T2> action, T1 param1, T2 param2) { 
    // TODO: Implement something like: 
    // Execute(action, param1, param2, null); 
} 

public void Execute<T1,T2,T3>(Action<T1,T2,T3> action, T1 param1, T2 param2, T3 param3) { 
    DoStuff(); 
    action(param1, param2, param3) 
    DoMoreStuff(); 
} 

// OR any other type of higher order function-solution 
public void Execute(Action action, params object[] parameters) { ... } // ??? 

yöntemlerin içeriği eylem ve parametreleri yürütülmesi haricinde tamamen aynı: Bu aşırı yükleri uygulamak için, en dolaysız ve kompakt yolu nedir. Bu sorunu çözmek için, C# 4.0'a özgü herhangi bir özellik kullanmıyorsanız,

cevap

8

yöntem içeriği yürütülmesi işlemi ve parametreleri hariç tam olarak aynıdır. Bir higher order function kullanmak için bağırabilme Senden sonra zaten (eylem yürütme ve parametrelerini) Zaten oradayız değişiyor tüm bitleri parametreli

. Üzgünüm, bu aşırı yükleri manuel olarak uygulamanız gerekecek gibi görünüyor.

Yalnızca boş anahtarlar kullanılarak zincirleme, temsilciler geçmediğinden çalışmayacaktır. Ne yapabilirdiek argümanlar kalkmasına bir lambda içine geçirilen eylem/fonk sarın geçerli:

public void Execute(Action<T> action, T param) { 
    Execute((a, _) => action(a) , param, null); 
} 

public void Execute(Action<T1, T2> action, T1 param1, T2 param2) { 
    Execute((a, b, _) => action(a, b) , param1, param2, null); 
} 

public void Execute(Action<T1, T2, T3> action, T1 param1, T2 param2, T3 param3) { 
    DoStuff(); 
    action(param1, param2, param3) 
    DoMoreStuff(); 
} 
+0

Daha yüksek bir sipariş fonksiyonu çözümü sunmaktan lütfen çekinmeyin. –

+0

@Seb: Üst düzey işlevle ilgili olarak: İşleminizi parametreleştirerek zaten varsınız. –

5

Bu iyi yaklaşım aslında (zihin Johannes gözüyle tutarak size ettik ki aynı zamanda daha yüksek kullanılır sipariş işlevi), en tür dostu olduğu için (delegeler otomatik olarak doğru numara ve argüman türleri ile eşleştirilecektir) ve rahatsız edici herhangi bir DynamicInvoke çağrı gerektirmez. Bununla birlikte, son yöntem tanımınız sorunludur, ancak. Doğası gereği bir Action, herhangi bir parametre kabul etmez, bu nedenle params object[] argümanı ile güzel oynamayacaktır. Eğer bağımsız değişken bir dizi kabul eden bir nihai aşırı istiyorsanız, sadece bu yöntem çağrısı için, sonuçta DynamicInvoke ile gider:

public void Execute(Delegate action, params object[] parameters) 
{ 
    DoStuff(); 
    action.DynamicInvoke(parameters); 
    DoMoreStuff(); 
} 

Fakat Johannes ne dediğini genişletmek için, onun temelde olduğunu düşünüyorum böyle bir şey demeye: vb

public Action<T1, T2, T3> CreateAction<T1, T2, T3>(Action action) 
{ 
    return (T1 x, T2 y, T3 z) => action(); 
} 

public Action<T1, T2, T3> CreateAction<T1, T2, T3>(Action<T1> action, T1 arg) 
{ 
    return (T1 x, T2 y, T3 z) => action(arg); 
} 

Ve - diğer bir deyişle, ne zaten yaptık ama genel bir bağlamda böylece kod başka yerlerde yeniden kullanılabilir.