72

この男が IComparer または IEqualityComparer が期待される ArrayList.Sort(IComparer here) または IEnumerable.SequenceEqual(IEnumerable list, IEqualityComparer here) にラムダ式を渡したコードを見たことがあります。

見たのか、ただ夢を見ているだけなのかは定かではありません。そして、これらのコレクションのいずれにも、メソッド シグネチャで Func<> またはデリゲートを受け入れる拡張機能が見つからないようです。

そのようなオーバーロード/拡張メソッドはありますか? または、そうでない場合、このようにいじくり回して、単一メソッド インターフェイスが期待されるアルゴリズム (読み取りデリゲート) を渡すことは可能ですか?

更新 ありがとう、みんな。私もそう思っていました。夢見ていたに違いない。変換の書き方を知っています。私はそのようなものを見たことがあったのか、それとも単に見たと思っただけなのか確信が持てなかった.

さらに別の更新 ほら、ここで、そのようなインスタンスを1つ見つけました。やっぱり夢じゃなかった。この男がここで何をしているのか見てください。何を与える?

そして、ここに別の更新 があります。わかりました。男はComparison<T>過負荷を使用しています。良い。素晴らしいですが、完全に誤解を招く傾向があります。いいけど。ありがとう。

4

8 に答える 8

33

IComparer を期待する基本ライブラリのほとんどの場合、比較を期待するオーバーロードがあると思うので、実際に何が役立つかはよくわかりませんが、記録のためだけに:

.Net 4.5 では、比較から IComparer を取得するメソッドを追加しました: Comparer.Create

そのため、ラムダを渡して IComparer を取得できます。

于 2012-06-11T10:03:59.250 に答える
13

Array.Sort メソッドにラムダを指定できます。これは、タイプ T の 2 つのオブジェクトを受け取り、整数を返すメソッドが必要なためです。そのため、次の定義のラムダを提供できます(a, b) => a.CompareTo(b)。整数配列の降順ソートを行う例:

int[] array = { 1, 8, 19, 4 };

// descending sort 
Array.Sort(array, (a, b) => -1 * a.CompareTo(b));
于 2010-07-06T20:18:01.767 に答える
7
public class Comparer2<T, TKey> : IComparer<T>, IEqualityComparer<T>
{
    private readonly Expression<Func<T, TKey>> _KeyExpr;
    private readonly Func<T, TKey> _CompiledFunc
    // Constructor
    public Comparer2(Expression<Func<T, TKey>> getKey)
    {
        _KeyExpr = getKey;
        _CompiledFunc = _KeyExpr.Compile();
    } 

    public int Compare(T obj1, T obj2)
    {
        return Comparer<TKey>.Default.Compare(_CompiledFunc(obj1), _CompiledFunc(obj2));
    }

    public bool Equals(T obj1, T obj2)
    { 
        return EqualityComparer<TKey>.Default.Equals(_CompiledFunc(obj1), _CompiledFunc(obj2));
    }

    public int GetHashCode(T obj)
    {
         return EqualityComparer<TKey>.Default.GetHashCode(_CompiledFunc(obj));
    }
}

このように使用します

ArrayList.Sort(new Comparer2<Product, string>(p => p.Name));
于 2010-07-06T20:22:50.750 に答える
5

直接渡すことはできませんが、 aLambdaComparerを除くクラスを定義しFunc<T,T,int>、それを で使用することで渡すことができますCompareTo

それほど簡潔ではありませんが、 のクリエイティブな拡張メソッドを使用して短くすることができますFunc

于 2010-07-06T20:21:42.487 に答える
4

これらのメソッドには、インターフェイスの代わりにデリゲートを受け入れるオーバーロードはありませんが、次のようになります。

  • 通常、渡すデリゲートを介して、より単純なソートキーを返すことができますEnumerable.OrderBy
  • Enumerable.Select同様に、呼び出す前に呼び出すことができますEnumerable.SequenceEqual
  • IEqualityComparer<T>の観点から実装するラッパーを書くのは簡単なはずです。Func<T, T, bool>
  • F# では、ラムダの観点からこの種のインターフェイスを実装できます :)
于 2010-07-06T20:19:46.183 に答える
3

ラムダと、場合によっては 2 つの異なる要素タイプで使用するためにこの関数が必要な場合:

static class IEnumerableExtensions
{
    public static bool SequenceEqual<T1, T2>(this IEnumerable<T1> first, IEnumerable<T2> second, Func<T1, T2, bool> comparer)
    {
        if (first == null)
            throw new NullReferenceException("first");

        if (second == null)
            throw new NullReferenceException("second");

        using (IEnumerator<T1> e1 = first.GetEnumerator())
        using (IEnumerator<T2> e2 = second.GetEnumerator())
        {
            while (e1.MoveNext())
            {
                if (!(e2.MoveNext() && comparer(e1.Current, e2.Current)))
                    return false;
            }

            if (e2.MoveNext())
                return false;
        }

        return true;
    }
}
于 2016-07-26T16:13:29.783 に答える
3

私は夢説に一票。

オブジェクトが期待される場所に関数を渡すことはできません: System.Delegate の派生物 (ラムダとは何か) は、これらのインターフェイスを実装していません。

おそらくご覧になったのはConverter<TInput, TOutput>、ラムダによってモデル化できるデリゲートの使用です。Array.ConvertAllは、このデリゲートのインスタンスを使用します。

于 2010-07-06T20:17:20.453 に答える