2010-08-18 3 views
7

작업 (또는 Func)을 사용하는 메서드가 필요하지만 작업의 매개 변수 수가 혼합되어 있습니다.C# Action 및 Func 매개 변수 오버로드

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) { ... } // ??? 

방법의 내용은 작업 및 해당 매개 변수의 실행을 제외하고 동일하다 :이 오버로드를 구현하는 가장 정직하고 컴팩트 한 방법은 무엇입니까.

가능하면이 문제를 해결하기 위해 C# 4.0 관련 기능을 사용하지 마십시오.

답변

8

방법의 내용은 실행 동작 및 파라미터를 제외 정확히 동일하다.

higher order function을 사용하는 경우 비명을 지르지 만, 변경중인 모든 비트 (동작 및 매개 변수 실행)가 이미 매개 변수화되어 있기 때문에 이미 이미 존재합니다. 죄송합니다. 이러한 과부하를 수동으로 구현해야합니다.

전달 된 대리자가 일치하지 않기 때문에 null을 사용하여 연결하는 것만으로는 작동하지 않습니다. 당신이 할 수있는 것은추가 인수를 벗겨 람다 내부에 전달 된 액션/FUNC을 포장입니다 :

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

고차원 함수 솔루션도 자유롭게 제공하십시오. –

+0

@Seb : 고차 함수에 관해서 : 당신은 당신의 행동을 매개 변수화함으로써 이미 그곳에 있습니다. –

5

이 가장 좋은 방법은 실제로 (마음 요하네스의 관점에서 유지하는 것은 당신이했습니다 수있는 또한 더 높은 사용 order 함수). 가장 형식이 쉽기 때문에 (대리자는 올바른 숫자와 형식의 인수와 자동으로 일치 함) 번거로운 DynamicInvoke 호출을 필요로하지 않습니다.

그러나 마지막 메서드 정의에는 문제가 있습니다. 성격 상 Action은 매개 변수를 허용하지 않으므로 params object[] 인수를 사용하면 문제가 해결되지 않습니다. 당신은 가변 인자를받는 최종 과부하를 원하는 경우에, 난 그냥이 메서드 호출, 결국 DynamicInvoke와 함께 가고 싶어요 :

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

그러나 요하네스이 한 말에 확장, 나는 그가 기본적으로 생각 이런 식으로 점점 : 등등

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

과 - 즉, 당신은 무엇을 이미 완료했지만, 일반적인 상황에서되도록 코드가 다른 장소에서 다시 사용할 수 있습니다.