0

ラムダとデリゲートのいくつかの基本が欠けているに違いありません。ここに行きます..

「ほぼ」同じことを行う2つの関数があります。それらを1つの関数に書き込んで「必要な」引数を渡すことで、それらをOOPする必要があります。

2 つの関数は、大まかに次のようになります。

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

関数はもっと冗長なので、本当に DRY したいと思います。お気づきのように、2 つの機能の唯一の違いは、2 つのポジショニング機能です。

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

yPoint += cb.Height + 12;

上記の式を引数として渡すことで、上記の 2 つの関数を 1 つにするにはどうすればよいですか? 私が見つけた問題は、変数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するより良い方法はありますか?

編集:私が渡そうとしている2つの式は、いくつかの動的コントロール(水平、垂直、斜め、ジグザグなど)を配置します。関数はすでに 4 つの異なる場所から呼び出されており、スケーリングされます。式自体を取得するために、呼び出しクラスから多くの計算を行います。そのため、 (別の Utility クラスにある) 関数if else内でロジックを実行することは、私が望むものではありません。Populateすべてのメソッドの唯一の変更点は、foreach 内の式の配置です。したがって、この場合の引数をどのように渡すことができるかを探しています。

4

4 に答える 4

2

Lambdas を介して実行する必要がある場合は、次の代替手段があります。

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

2 つの呼び出しは次のようになります。

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より簡潔です。

于 2012-07-05T00:19:21.670 に答える
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 が必要な場合は呼び出しPopulate(valueofypoint, true)、 Populate2 が必要な場合はPopulate(valueofypoint, false)呼び出します。

于 2012-07-05T00:04:22.623 に答える
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);

これはあなたが期待しているものですか?

于 2012-07-05T00:40:14.390 に答える
0

あなたのアイデアとNikhilの提案を組み合わせる:

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;
}
于 2012-07-05T00:13:44.630 に答える