I have written about LINQ in the past and I truly believe it is the gateway to a better way of programming, surprisingly I have never used the Distinct method before this week. So I was rather surprised that for all my efforts simply using the Distinct method would not work even for an object as simple as the following:
public class WordViewModel
public class WordViewModel
{
public string Word
{
get {}
set {}
}
}
public class WordViewModel
{
public string Word
{
get {}
set {}
}
}
Basically this is a function of the fact that even for a type as simple this, LINQ really does not know how to use the property ‘Word’ to determine if a type is unique or not. So in order to use the Distinct method effectively we have to tell LINQ how to compare our types use the IEqualityComparer as follows
// Custom comparer for the Product class
class WordComparer : IEqualityComparer<WordViewModel>
// Words are equal if their names are equal.
public bool Equals(WordViewModel x, WordViewModel y)
if (Object.ReferenceEquals(x, y)) return true;
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
//Check whether the properties are equal.
// GetHashCode() should return the same value.
public int GetHashCode(WordViewModel word)
if (Object.ReferenceEquals(word, null)) return 0;
int hashProductName = word.Word == null ? 0 : word.Word.GetHashCode();
int hashProductCode = word.Word.GetHashCode();
//Get the hash code for Word
return hashProductName ^ hashProductCode;
// Custom comparer for the Product class
class WordComparer : IEqualityComparer<WordViewModel>
{
// Words are equal if their names are equal.
public bool Equals(WordViewModel x, WordViewModel y)
{
if (Object.ReferenceEquals(x, y)) return true;
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
return false;
//Check whether the properties are equal.
return x.Word == y.Word;
}
// GetHashCode() should return the same value.
public int GetHashCode(WordViewModel word)
{
if (Object.ReferenceEquals(word, null)) return 0;
int hashProductName = word.Word == null ? 0 : word.Word.GetHashCode();
int hashProductCode = word.Word.GetHashCode();
//Get the hash code for Word
return hashProductName ^ hashProductCode;
}
}
// Custom comparer for the Product class
class WordComparer : IEqualityComparer<WordViewModel>
{
// Words are equal if their names are equal.
public bool Equals(WordViewModel x, WordViewModel y)
{
if (Object.ReferenceEquals(x, y)) return true;
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
return false;
//Check whether the properties are equal.
return x.Word == y.Word;
}
// GetHashCode() should return the same value.
public int GetHashCode(WordViewModel word)
{
if (Object.ReferenceEquals(word, null)) return 0;
int hashProductName = word.Word == null ? 0 : word.Word.GetHashCode();
int hashProductCode = word.Word.GetHashCode();
//Get the hash code for Word
return hashProductName ^ hashProductCode;
}
}
So then my simple Distinct method gets passed my customized comparer and works like a charm!
var newlist = new List<WordViewModel>(
list.Where(s => !s.Word.StartsWith("Start"))
.Where(s => s.Word.Length > 5)
.OrderBy(c => c.Word.Length).ThenBy(s => s.Word))
.Distinct(new WordComparer());
var newlist = new List<WordViewModel>(
list.Where(s => !s.Word.StartsWith("Start"))
.Where(s => s.Word.Length > 5)
.OrderBy(c => c.Word.Length).ThenBy(s => s.Word))
.Distinct(new WordComparer());
var newlist = new List<WordViewModel>(
list.Where(s => !s.Word.StartsWith("Start"))
.Where(s => s.Word.Length > 5)
.OrderBy(c => c.Word.Length).ThenBy(s => s.Word))
.Distinct(new WordComparer());
Comments are closed.