Imagine if you can write it as follows:
Var p1 = products. Distinct (p => p. ID );
Var p2 = products. Distinct (p => p. Name );
Using a simple lambda as a parameter also conforms to the consistent style of Linq.
You can achieve this by using the extension method:
Distinct Extension Method
First, create a general comparison class to implement the IEqualityComparer <T> interface:
Using System;
Using System. Collections. Generic;
Using System. Runtime. CompilerServices;
Using System. Linq;
Public class CommonEqualityComparer <T, V>: IEqualityComparer <T>
{
Private Func <T, V> keySelector;
Public CommonEqualityComparer (Func <T, V> keySelector)
{
This. keySelector = keySelector;
}
Public bool Equals (T x, T y)
{
Return EqualityComparer <V>. Default. Equals (keySelector (x), keySelector (y ));
}
Public int GetHashCode (T obj)
{
Return EqualityComparer <V>. Default. GetHashCode (keySelector (obj ));
}
}
In row 3, The EqualityComparer <T> class is used. This article provides a brief description.
With the help of the above class, the Distinct extension method is very easy to write:
1
Public static class DistinctExtensions
{
Public static IEnumerable <T> Distinct <T, V> (this IEnumerable <T> source, Func <T, V> keySelector)
{
Return source. Distinct (new CommonEqualityComparer <T, V> (keySelector ));
}
}
It's easy!
Example of Distinct
Based on ID:
Var data1 = new Person [] {
New Person {ID = 1, Name = "Crane chongtian "},
New Person {ID = 1, Name = "ldp "}
};
Var ps1 = data1
. Distinct (p => p. ID)
. ToArray ();
According to Name:
Var data2 = new Person [] {
New Person {ID = 1, Name = "Crane chongtian "},
New Person {ID = 2, Name = "Crane chongtian "}
};
Var ps2 = data2
. Distinct (p => p. Name)
. ToArray ();
After reading the reply, I made some improvements and recommended the following methods:
Improvement
A friend mentioned in the reply that "it is not difficult to exclude duplicate strings without case sensitivity". You just need to improve the code above and then OK:
CommonEqualityComparer <T, V> class:
Using System;
Using System. Collections. Generic;
Using System. Runtime. CompilerServices;
Using System. Linq;
Public class CommonEqualityComparer <T, V>: IEqualityComparer <T>
{
Private Func <T, V> keySelector;
Private IEqualityComparer <V> comparer;
Public CommonEqualityComparer (Func <T, V> keySelector, IEqualityComparer <V> comparer)
{
This. keySelector = keySelector;
This. comparer = comparer;
}
Public CommonEqualityComparer (Func <T, V> keySelector)
: This (keySelector, EqualityComparer <V>. Default)
{}
Public bool Equals (T x, T y)
{
Return comparer. Equals (keySelector (x), keySelector (y ));
}
Public int GetHashCode (T obj)
{
Return comparer. GetHashCode (keySelector (obj ));
}
}
Distinct extension method:
Public static class DistinctExtensions
{
Public static IEnumerable <T> Distinct <T, V> (this IEnumerable <T> source, Func <T, V> keySelector)
{
Return source. Distinct (new CommonEqualityComparer <T, V> (keySelector ));
}
Public static IEnumerable <T> Distinct <T, V> (this IEnumerable <T> source, Func <T, V> keySelector, IEqualityComparer <V> comparer)
{
Return source. Distinct (new CommonEqualityComparer <T, V> (keySelector, comparer ));
}
}
With optional parameters, the two extension methods can also combine one:
Public static IEnumerable <T> Distinct <T, V> (this IEnumerable <T> source, Func <T, V> keySelector,
IEqualityComparer <V> comparer = EqualityComparer <V>. Default)
{
Return source. Distinct (new CommonEqualityComparer <T, V> (keySelector, comparer ));
}
(Likewise, the two constructors of the CommonEqualityComparer <T, V> class can be combined into one)
Example:
Var data3 = new Person [] {
New Person {ID = 1, Name = "LDP "},
New Person {ID = 2, Name = "ldp "}
};
Var ps3 = data3
. Distinct (p => p. Name, StringComparer. CurrentCultureIgnoreCase)
. ToArray ();
EqualityComparer <T> class description
EqualityComparer <T> provides a base class for The Implementation of The IEqualityComparer <T> generic interface. It has five important sub-classes in. net 4. See:
These five subclasses use the equality comparison of different types of data. We can know a little about the class name.
These five subclasses are internal classes (internal) and cannot be accessed directly. The EqualityComparer <T> class provides a simple property Default. EqualityComparer <T> loads different subclasses based on the input T type and caches them to improve performance.