2009-07-31 15 views
19

私は次のような基準を渡すことができるDistinct拡張メソッドを作成しています。どのようにFunc <T,TResult>は機能しますか?

persons.Distinct(p => p.Name); 

私は、Webからのコードを得たが、私はFunc<T, TResult>の目的を理解することに苦労しています。また、私がp => p.Nameと言うときは、StringNameを送っていますか、それとも完全なPersonオブジェクトを送っていますか?ここでは新しい個別の方法は次のとおりです。

public static class ExtensionMethods 
{ 
    public static IEnumerable<T> Distinct<T>(
     this IEnumerable<T> list, Func<T,object> checker) 
    { 
     return list.Distinct(new GenericComparer<T>(checker)); 
    } 
} 

public class GenericComparer<T> : IEqualityComparer<T> 
{ 
    private Func<T, object> _checker; 

    public GenericComparer(Func<T,object> checker) 
    { 
     _checker = checker; 
    } 

    public bool Equals(T x, T y) 
    { 
     return _checker(x).Equals(_checker(y)); 
    } 

    public int GetHashCode(T obj) 
    { 
     return _checker(obj).GetHashCode(); 
    } 
} 

そして、ここでは、使用ある:

static void Main(string[] args) 
{ 
    var persons = new List<Person>() 
    { 
     new Person() { Id = 1, Name = "Mary"}, 
     new Person() {Id = 2, Name="John"}, 
     new Person() { Id = 3, Name = "Mary"} 
    }; 

    var uniquePersons = persons.Distinct(p => p.Name); 

    foreach(var person in uniquePersons) 
    { 
     Console.WriteLine(person.Name); 
    } 
} 

答えて

34

あなたがこれを行うと:

persons.Distinct(p => p.Name); 

あなたは基本的に(オンザフライ機能を作成していますusing lambda expressions)、次のようになります。

string theFunction(Person p) 
{ 
    return p.Name; 
} 

これはFunc<Person,String>デリゲートの署名に適合する関数です。 Distinctメソッドはデリゲート(基本的には関数ポインタ)を使用して、要素が別個かどうかを判断します。この場合、ユニークな文字列(上記の関数によって返されたもの)のみが「別個の」要素とみなされます。この代理人はあなたの "人"の各要素に対して実行可能であり、それらの関数の結果が使用されます。次に、これらの要素からシーケンス(IEnumerable<Person>)を作成します。

+0

+1 "しかし、あなたの場合、他の要素に同じ名前がない場合、要素は区別されます。ソース内の複数の項目の名前が同じ場合、結果の最初の項目だけが結果に表示されます。 "また、Distict()メソッドのオーバーロードはセレクタを必要としません - あなた自身で記述しましたか? –

+0

OP質問はDistinctエクステンションがどのように定義されているかを示しています... – ShuggyCoUk

+0

はい、私はインターネットのDistinct拡張メソッドを持っています!私はそれを自分で書いていませんでした! –

8
Func<T, TResult> 

は、(タイプTの)1つのパラメータを受け入れ、(タイプTResultの)オブジェクトを返す関数を定義します。あなたはPersonオブジェクトを受け取り、文字列を返す関数をしたい場合は

あなたの場合

、...あなたがしたいと思うのと同じです

Func<Person, string> 

string Function(Person p) 
{ 
    return p.Name; 
} 
0

をあなた2人が同じ名前を持っている場合、2人が同じであるという前提の下で、別個の人々を取り戻している。

異なる名前のセットが必要な場合は、

IEnumerable<String> names = persons.Select(p => p.Name).Distinct(); 
関連する問題