exceptionWineList is string[] , but originalWineCellar is List<WineCellar> , WineCellar not string , so it makes no sense to execute Except between them.
You could just as easily do
// use HashSet for look up performance. var exceptionWineSet = new HashSet<string>(exceptionWineList); var result = orginalWineCellar.Where(w => !exceptionWineSet.Contains(w.Wine));
I think you are hinting at your question, is it something like
WineCellar : IEquatable<string> { ... public bool Equals(string other) { return other.Equals(this.wine, StringComparison.Ordinal); } }
which allows you to equate WineCellar with string s.
However, if I were to rework your model, I would come up with something like
enum WineColour { Red, White, Rose } enum WineRegion { Bordeaux, Rioja, Alsace, ... } enum GrapeVariety { Cabernet Sauvignon, Merlot, Ugni Blanc, Carmenere, ... } class Wine { public string Name { get; set; } public string Vineyard { get; set; } public WineColour Colour { get; set; } public WineRegion Region { get; set; } public GrapeVariety Variety { get; set; } } class WineBottle { public Wine Contents { get; set; } public int Millilitres { get; set; } public int? vintage { get; set; } } class Bin : WineBottle { int Number { get; set; } int Quantity { get; set; } } class Cellar : ICollection<WineBottle> { ... }
Then you can see that there are several ways to compare Wine , and I can filter out Cellar for one or more Wine properties. Therefore, I may be inclined to be somewhat flexible,
class WineComparer : EqualityComparer<Wine> { [Flags] public Enum WineComparison { Name = 1, Vineyard= 2, Colour = 4, Region = 8, Variety = 16, All = 31 } private readonly WineComparison comparison; public WineComparer() : this WineComparer(WineComparison.All) { } public WineComparer(WineComparison comparison) { this.comparison = comparison; } public override bool Equals(Wine x, Wine y) { if ((this.comparison & WineComparison.Name) != 0 && !x.Name.Equals(y.Name)) { return false; } if ((this.comparison & WineComparison.Vineyard) != 0 && !x.Vineyard.Equals(y.Vineyard)) { return false; } if ((this.comparison & WineComparison.Region) != 0 && !x.Region.Equals(y.Region)) { return false; } if ((this.comparison & WineComparison.Colour) != 0 && !x.Colour.Equals(y.Colour)) { return false; } if ((this.comparison & WineComparison.Variety) != 0 && !x.Variety.Equals(y.Variety)) { return false; } return true; } public override bool GetHashCode(Wine obj) { var code = 0; if ((this.comparison & WineComparison.Name) != 0) { code = obj.Name.GetHashCode(); } if ((this.comparison & WineComparison.Vineyard) != 0) { code = (code * 17) + obj.Vineyard.GetHashCode(); } if ((this.comparison & WineComparison.Region) != 0) { code = (code * 17) + obj.Region.GetHashCode(); } if ((this.comparison & WineComparison.Colour) != 0) { code = (code * 17) + obj.Colour.GetHashCode(); } if ((this.comparison & WineComparison.Variety) != 0) { code = (code * 17) + obj.Variety.GetHashCode(); } return code; } }
it probably seems like a lot of effort, but it makes sense. Say we wanted all the wine except the red Rioja in your basement to do something like:
var comparison = new WineComparer( WineComparison.Colour + WineComparison.Region); var exception = new Wine { Colour = WineColour.Red, Region = WineRegion.Rioja }; var allButRedRioja = cellar.Where(c => !comparison.Equals(c.Wine, exception));