2012-11-23 34 views
0

最好用代碼解釋我的意圖。所以現在我有以下代碼:擺脫函數的參數

class A, IInterfaceUsedByB 
{ 
} 

class B 
{ 
    void func(A someObject) 
    { 
     func2(someObject, 1); 
     func3(someObject, "string"); 
     func4(someObject, new MyObject()); 

     var anotherObject = someObject.NewInstance; 
     func2(anotherObject, 1); 
     ....................... 
    } 
    func2(A someObject, int val); 
    func3(A someObject, string val); 
    func4(A someObject, C val); 
} 

func2func3func4確實需要someObject引用。我想改變這

void func(A someObject) 
{ 
    with(someObject, 
      () => 
       { 
        func2(1); 
        func3("string"); 
        func4(new MyObject()); 
       } 
     ); 
    var anotherObject = someObject.NewInstance; 
    with(anotherObject, 
      () => 
       { 
        func2(1); 
        ....................... 
       } 
     ); 
} 

甚至更​​好的

void func(A someObject) 
{ 
    func2(1); 
    func3("string"); 
    func4(new MyObject()); 
} 

,這樣我就不用拖動該someObject,但我仍然應該能夠使用它裏面func2,3 4。換句話說,就像爲特定的代碼塊設置一些上下文對象。我可以使用這三種語言(C#,F#或IronPython)中的任何一種。

UPDATE在理想的解決方案中,B類將獨立於A. func*函數僅依賴於包含2個方法的A的小接口。

UPDATE2 someObject對於不同的函數調用可以不同。

UPDATE3我不認爲有一種方法只能用類,接口或擴展方法等語言基元來完成此操作。我認爲解決方案可能會使用更多的黑客工具,例如屬性,反射或F#的計算工作流程特性。或者可能是IronPython的一些動態功能。基本上我想要做的是創建一個小型嵌入式DSL。

+1

聽起來像你正在尋找一個全局變量? – Cameron

+1

除了上述兩個註釋/選項之外,也許您可​​以使用諸如部分函數應用程序或柯里格之類的東西:http://msmvps.com/blogs/jon_skeet/archive/2012/01/30/currying-vs-partial-function -application.aspx –

+0

@rid'func *'已經是另一個類的方法了。理想情況下,someObject和'func *'類應該是彼此獨立的,所以我可以輕鬆地用另一個類替換someObject而不更改'func *的類 – Max

回答

1

部分功能應用程序可能適合你。

// object for example first param 
var objectInstance = new object(); 

// partial function application 
var func2Partial = new Action<int>((i) => func2(objectInstance, i)); 
func2Partial(5); 

如果FUNC2返回的東西,那麼你就需要使用Func鍵<>而非行動<>

另外,如下面的擴展方法,我的意見可能是一種選擇也。

internal static class IInterfaceUsedByBExtender 
{ 
    internal static void Func2(this IInterfaceUsedByB obj, int value) 
    { 
    } 

} 

// caller 
someObject.Func2(5); 

另一個選項可能是F#中的管道運算符。我有基本的F#知識,但我認爲你可以用兩個參數定義一個函數,並使用管道運算符來填充第一個參數的值。因此,像:

let printnums x y = printfn "%A - %A" x y;; 

可以通過

4 |> printnums 5;; 

叫其輸出:

4 - 5 

隨着FUNC2你必須像

let func2 obj, num = ...; 
someObject |> func2 1;; 

的更多示例這個:stackoverflow: Piping F# Parameters

我希望這有助於!

+0

謝謝。這是我在發佈這個問題之前想要做的。但是代碼太複雜了。我會很好,如果我沒有寫所有'var func2Partial = new Action ((i)=> func2(objectInstance,i));' – Max

+1

如何在類型上做func2,func3和func4擴展方法someObject的?調用代碼然後會變成someObject.func2(5),但你不需要代表? – BrianB

+0

正如我在另一條評論中寫的,我希望'func *'獨立於someObject的類型。 – Max

0

如果所有這些函數都在一個對象(sameObject)上運行,看起來應該引入一個類並使它們成爲類方法。我不知道是什麼類型的someObject,但這裏是在C#中的例子:

class Workflow<T> 
    where T: class 
{ 
    private readonly T _someObject; 

    public Workflow(T someObject) 
    { 
     _someObject = someObject; 
    } 


    public void func() 
    { 
     func2(1); 
     func3("string"); 
     func4(new MyObject()); 
    } 

    private void func2(int a) 
    { 
     // use _someObject here 
    } 

    private void func3(string s) 
    { 
     // ... 
    } 
} 

// usage 
var flow = new Workflow(someObject); 
flow.f(); 
+0

謝謝,但對象是不一樣的。此外,我希望'func *'與someObject的類型正交 – Max

0
class A, IInterfaceUsedByB 
{ 
} 

class B<T> where T : A 
{ 
    private T m_SomeObject; 

    public B(T someobject) 
    { 
     m_Someobject = someobject; 
    } 
    void func() 
    { 
     func2(1); 
     func3("string"); 
     func4(new MyObject()); 
    } 
    func2(int val) { //Do whatever with m_SomeObject } 
    func3(string val) { //Do whatever with m_SomeObject } 
    func4(C val){ //Do whatever with m_SomeObject } 
} 
0

你可以寫一個函數,它接受一個A和返回FUNC2功能。 例如,如果FUNC2返回類型爲void(如果沒有,則使用函數功能< INT,返回類型>):

 Action<int> func2Gen(A someObject) 
     { 
      return i => Console.WriteLine(i+someObject.ToString()); 
     } 

然後,徘徊無論適合,可以聲明

var func2=func2Gen(someObject); 

並調用它:

func2(1);