5

以前に変数に割り当てたラムダ式の実行に問題があるようです。これが私がまとめた小さなC#サンプルプログラムです:

public class Program
{
    public static void Main(string[] args)
    {
        int[] notOrdered = { 3, 2, 5, 8, 1, 4, 7, 9, 6 };
        Print(notOrdered);
        
        IEnumerable<int> ascOrdered = Order(notOrdered, true);
        Print(ascOrdered);

        IEnumerable<int> descOrdered = Order(notOrdered, false);
        Print(descOrdered);
    }
    
    static IEnumerable<T> Order<T>(IEnumerable<T> enumerables, bool ascending)
    {
        Expression<Func<T, object>> selector = (z) => z; // simple for demo purposes; pretend it's complex
        if (ascending)
            return enumerables.OrderBy(z => selector);
        else
            return enumerables.OrderByDescending(z => selector);
    }
    
    static void Print<T>(IEnumerable<T> enumerables)
    {
        foreach(T enumerable in enumerables)
            Console.Write(enumerable.ToString() + " ");
        Console.WriteLine();
    }
}

私はそれがこの出力を生成することを望みます:

3 2 5 8 1 4 7 9 6

1 2 3 4 5 6 7 8 9

9 8 7 6 5 4 3 2 1

しかし、紛らわしいことに、次の出力が生成されます。

3 2 5 8 1 4 7 9 6

3 2 5 8 1 4 7 9 6

3 2 5 8 1 4 7 9 6

基本的には、2回入力しなくても、同じ式を2つの異なる順序付け操作に渡せるようにしたいので、selector事前に割り当てます。ラムダ式が非常に長く/乱雑で、混乱を複製したくないという実際のユースケースがあります。ここにあるような変数を参照するだけです。

それで、a)現在の出力の原因は何ですか?b)必要な出力を取得するにはどうすればよいですか?

4

3 に答える 3

9

コードでは、式を使用しません。

あなたのコードは次のようなものです:

object selector = new object();
if (ascending)
    return enumerables.OrderBy(z => selector);
else
    return enumerables.OrderByDescending(z => selector);

コードには式がないはずです。

Func<T, object> selector = (z) => z;
if (ascending)
    return objects.OrderBy(selector);
else
    return objects.OrderByDescending(selector);

ただし、(テスト目的などで)式が本当に必要な場合は、次の前にコンパイルしてください。

Expression<Func<T, object>> selector = (z) => z;
var compiledExpression = selector.Compile();
if (ascending)
    return objects.OrderBy(compiledExpression);
else
    return objects.OrderByDescending(compiledExpression);
于 2013-02-01T21:57:37.417 に答える
7

a)現在、Expression<Func<T,object>>オブジェクト自体ではなく、(実際の式インスタンス)で並べ替えています。これにより、順序付けは常に同じオブジェクトを使用して順序付けされます。つまり、order by句は何も変更しません(式の同じインスタンスに等しいため、すべての項目は「等しい」です)。

b)私はあなたが望むと信じています:

static IEnumerable<T> Order<T>(IEnumerable<T> enumerables, bool ascending)
{
    if (ascending)
        return enumerables.OrderBy(z => z);
    else
        return enumerables.OrderByDescending(z => z);
}
于 2013-02-01T21:57:46.490 に答える
1

式のインスタンスselectorを比較するだけで、呼び出しを行うのではありません。正しい方法は

static IEnumerable<T> Order<T>(IEnumerable<T> enumerables, bool ascending)
{
    Func<T, object> selector = (z) => z;
    if (ascending)
        return enumerables.OrderBy(z => selector(z));
    else
        return enumerables.OrderByDescending(z => selector(z));
}
于 2013-02-01T22:03:04.977 に答える