2012-07-04 45 views
0

我必須缺少lambdas和委託的一些基本原理。在這裏它去..當表達式中的變量在方法範圍內時,如何將表達式傳遞給方法

我有兩個功能,「幾乎」相同的東西。我需要通過將它們寫入一個函數並傳遞「必要」參數來將它們OOP。

兩個功能大致是這樣的:

private static bool Populate1(int yPoint) 
{ 
    //--------------------------------- 
    //-------------------------------- 
    int xPoint = 0; 

    foreach (var item in collection) 
    { 
     ComboBox cb = AddControl_Combo(item, xPoint, yPoint); 

     xPoint += cb.Width + 12; 
     yPoint = 0; 
    } 

    //------------------------------- 
    //------------------------------- 

    return true; 
} 

private static bool Populate2(int yPoint) 
{ 
    //--------------------------------- 
    //-------------------------------- 
    int xPoint = 0; 

    foreach (var item in collection) 
    { 
     ComboBox cb = AddControl_Combo(item, xPoint, yPoint); 

     yPoint += cb.Height + 12; 
    } 

    //--------------------------------- 
    //-------------------------------- 

    return true; 
} 

的功能是很多更詳細的,所以我想真幹他們。正如人們可以看到,在這兩個功能,唯一的區別是兩個定位功能

xPoint += cb.Width + 12; 
yPoint = 0; 

yPoint += cb.Height + 12; 

我如何通過將上述表達式作爲參數,作出上述兩個功能合爲一體?我發現的麻煩是變量xPointcb是非常功能範圍內的變量!

這裏是我的嘗試和成功,但在我看來,不優雅:

private static bool Populate(ref int xPoint, ref int yPoint, ref ComboBox cb, 
           Action positioningFunc) 
{ 
    foreach (var item in collection) 
    { 
     cb = AddControl_Combo(item, xPoint, yPoint); 

     positioningFunc(); 
    } 

    return true; 
} 

,並稱之爲:

int xPoint = 0; 
int yPoint = 0; 
ComboBox cb = null; 
return Populate(ref xPoint, ref yPoint, ref cb,() => 
{ 
    xPoint += cb.Width + 12; 
    yPoint = 0; 
}); 

int xPoint = 0; 
int yPoint = 19; 
ComboBox cb = null; 
return Populate(ref xPoint, ref yPoint, ref cb,() => 
{ 
    yPoint += cb.Height + 12; 
}); 

有沒有更好的辦法到OOP他們?

編輯:我試圖通過定位一些動態控件(水平,垂直,對角線,鋸齒形等)的兩個表達式。該功能已經從4個不同的地方調用並可以擴展。爲了獲得表達式本身,我們從調用類中進行了大量計算。所以在Populate函數(它在一個獨立的Utility類中)內部執行if else邏輯並不是我想要的。所有方法中唯一的變化是那些在foreach中定位表達式的方法。所以我正在尋找如何通過這種情況下的論據。

+0

在lambda中使用參數。 – SLaks

+0

您正在使用lamdas添加一些開銷(函數調用並減少本地優化的機會)。對於大多數無關緊要的代碼,但如果您有很多可能會對用戶感知產生影響的點。 –

+0

@SLaks我不擅長lambda ..你能發表一個示例代碼嗎?我不確定如何在lambda中使用參數,然後在方法 – nawfal

回答

2

如果你需要它通過Lambda表達式做這裏的一種替代方案:

private static bool Populate(int yPoint, Func<ComboBox, Point, Point> modifier) 
{ 
    var point = new Point (0, yPoint); 
    foreach (var item in collection) 
    { 
     ComboBox cb = AddControl_Combo(item, point.X, point.Y); 
     point = modifier(cb, point); 
    } 
    return true; 
} 

而且,這兩個電話是:

Populate(0, (cb, point) => new Point(point.X + cb.Width + 12, 0)); 
Populate(0, (cb, point) => new Point(0, point.Y + cb.Height + 12)); 

您也可以使用Tuple<int, int>,但Point更簡潔。

+0

謝謝了。正是我需要的。 – nawfal

+0

沒有問題。並感謝編輯;) –

1

簡單的邏輯

private static bool Populate(int yPoint, bool flag) 
{ 
    int xPoint = 0; 

    foreach (var item in collection) 
    { 
     var ComboBox cb = AddControl_Combo(item, xPoint, yPoint); 

     if(flag) 
     { 
      xPoint += cb.Width + 12; 
      yPoint = 0; 
     } 
     else 
     { 
      yPoint += cb.Height + 12; 
     } 
    } 

    return true; 
} 

當你想Populate1,呼籲Populate2呼叫Populate(valueofypoint, true)Populate(valueofypoint, false)

+0

對不起,我將編輯我的問題。這不是我以後.. – nawfal

+0

吻,我喜歡它。 –

0

結合你的想法和尼基爾建議:

private static bool Populate(int yPoint, int position) 
{ 
    int xPoint = 0; 

    ComboBox cb; 

    Action positionFunction; 
    if (position == 1) 
    { 
      positionFunction =() => { 
        xPoint += cb.Width + 12; 
        yPoint = 0; 
      }; 
    } 
    else if (position ==2) 
    { 
      positionFunction =() => { yPoint += cb.Height + 12; }; 
    } 
    else 
    { 
      throw new Exception("Invalid position"); 
    } 

    foreach (var item in collection) 
    { 
     cb = AddControl_Combo(item, xPoint, yPoint); 

     positionFunction(); 
    } 

    return true; 
} 
1

這應該工作完全按照您的需要:

private static bool Populate(int yPoint, 
    Func<int, ComboBox, int> xStep, 
    Func<int, ComboBox, int> yStep) 
{ 
    int xPoint = 0; 

    foreach (var item in collection) 
    { 
     ComboBox cb = AddControl_Combo(item, xPoint, yPoint); 

     xPoint = xStep(xPoint, cb); 
     yPoint = yStep(xPoint, cb); 
    } 

    return true; 
} 

你只是把它就像這樣:

Populate(42, (x, cb) => x + cb.Width + 12, (y, cb) => 0); 
Populate(42, (x, cb) => 0, (y, cb) => y + cb.Width + 12); 

這是你期待什麼?

+0

更簡單。喜歡這個。但是我發現@Pablo Romeo的答案更容易打電話。 – nawfal

相關問題