From 42938063269aa7493924b07096aa8b5c8216064b Mon Sep 17 00:00:00 2001 From: Vladimir Pecanac Date: Sun, 1 Nov 2026 13:31:12 +0100 Subject: [PATCH] UsingExceptInCSharp: move to .NET 10 and MSTest 4, add ExceptBy, record, copies and duplicates examples --- .../UsingExceptInCSharp/Employee.cs | 8 ++-- .../UsingExceptInCSharp/EmployeeComparer.cs | 12 +---- .../UsingExceptInCSharp/EmployeeRecord.cs | 3 ++ .../ExceptMethodExamples.cs | 45 ++++++++++++++++- .../UsingExceptInCSharp/Program.cs | 13 ++++- .../UsingExceptInCSharp.csproj | 2 +- .../UsingExceptInCSharpTests.csproj | 10 ++-- .../UsingExceptUnitTests.cs | 48 ++++++++++++++++--- 8 files changed, 112 insertions(+), 29 deletions(-) create mode 100644 csharp-linq/UsingExceptInCSharp/UsingExceptInCSharp/EmployeeRecord.cs diff --git a/csharp-linq/UsingExceptInCSharp/UsingExceptInCSharp/Employee.cs b/csharp-linq/UsingExceptInCSharp/UsingExceptInCSharp/Employee.cs index b71c624416..65f7741fb3 100644 --- a/csharp-linq/UsingExceptInCSharp/UsingExceptInCSharp/Employee.cs +++ b/csharp-linq/UsingExceptInCSharp/UsingExceptInCSharp/Employee.cs @@ -1,9 +1,9 @@ -namespace UsingExceptInCSharp; +namespace UsingExceptInCSharp; public class Employee { public int ID { get; set; } - public string Name { get; set; } + public string Name { get; set; } = string.Empty; public int Age { get; set; } - public string Department { get; set; } -} \ No newline at end of file + public string Department { get; set; } = string.Empty; +} diff --git a/csharp-linq/UsingExceptInCSharp/UsingExceptInCSharp/EmployeeComparer.cs b/csharp-linq/UsingExceptInCSharp/UsingExceptInCSharp/EmployeeComparer.cs index d248d912b0..e9a74625d4 100644 --- a/csharp-linq/UsingExceptInCSharp/UsingExceptInCSharp/EmployeeComparer.cs +++ b/csharp-linq/UsingExceptInCSharp/UsingExceptInCSharp/EmployeeComparer.cs @@ -1,5 +1,3 @@ -using System.Diagnostics.CodeAnalysis; - namespace UsingExceptInCSharp; public class EmployeeComparer : IEqualityComparer @@ -12,11 +10,5 @@ public bool Equals(Employee? x, Employee? y) return x.ID == y.ID && x.Name == y.Name && x.Age == y.Age && x.Department == y.Department; } - public int GetHashCode([DisallowNull] Employee obj) - { - var hashID = obj.ID.GetHashCode(); - var hashName = obj.Name.GetHashCode(); - - return hashID ^ hashName; - } -} \ No newline at end of file + public int GetHashCode(Employee obj) => HashCode.Combine(obj.ID, obj.Name); +} diff --git a/csharp-linq/UsingExceptInCSharp/UsingExceptInCSharp/EmployeeRecord.cs b/csharp-linq/UsingExceptInCSharp/UsingExceptInCSharp/EmployeeRecord.cs new file mode 100644 index 0000000000..f47d9e802c --- /dev/null +++ b/csharp-linq/UsingExceptInCSharp/UsingExceptInCSharp/EmployeeRecord.cs @@ -0,0 +1,3 @@ +namespace UsingExceptInCSharp; + +public record EmployeeRecord(int ID, string Name, int Age, string Department); diff --git a/csharp-linq/UsingExceptInCSharp/UsingExceptInCSharp/ExceptMethodExamples.cs b/csharp-linq/UsingExceptInCSharp/UsingExceptInCSharp/ExceptMethodExamples.cs index b7aa416688..ba00e192b5 100644 --- a/csharp-linq/UsingExceptInCSharp/UsingExceptInCSharp/ExceptMethodExamples.cs +++ b/csharp-linq/UsingExceptInCSharp/UsingExceptInCSharp/ExceptMethodExamples.cs @@ -31,6 +31,27 @@ public List GetEmployeesNotInSales() return empNotInSales; } + public List GetDistinctDifference() + { + int[] first = [1, 1, 2, 3, 3, 4]; + int[] second = [3]; + + return first.Except(second).ToList(); + } + + public List GetEmployeesNotInSalesFromCopies() + { + List salesCopies = new() + { + new Employee {ID = 1, Name = "John Doe", Age = 28, Department = "Sales"}, + new Employee {ID = 2, Name = "Emily Sanders", Age = 29, Department = "Sales"}, + new Employee {ID = 3, Name = "Benjamin Winters", Age = 30, Department = "Sales"}, + new Employee {ID = 12, Name = "Mary Jane", Age = 35, Department = "Sales"} + }; + + return employees.Except(salesCopies).ToList(); + } + public List GetEmployeesNotInITIgnoreCase() { var employeesNotInIT = employees.Select(e => e.Name) @@ -47,4 +68,26 @@ public List GetEmployeesNotInSalesUsingComparer() return employees.Except(employeesInSales, comparer).ToList(); } -} \ No newline at end of file + + public List GetEmployeeRecordsNotInSales() + { + List staff = new() + { + new EmployeeRecord(1, "John Doe", 28, "Sales"), + new EmployeeRecord(4, "Sheila Foxx", 31, "Marketing"), + new EmployeeRecord(6, "Grace Jones", 32, "IT") + }; + + List sales = new() + { + new EmployeeRecord(1, "John Doe", 28, "Sales") + }; + + return staff.Except(sales).ToList(); + } + + public List GetEmployeesNotInITByID() + { + return employees.ExceptBy(employeesIT.Select(e => e.ID), e => e.ID).ToList(); + } +} diff --git a/csharp-linq/UsingExceptInCSharp/UsingExceptInCSharp/Program.cs b/csharp-linq/UsingExceptInCSharp/UsingExceptInCSharp/Program.cs index 3751555cbd..ddf0f39670 100644 --- a/csharp-linq/UsingExceptInCSharp/UsingExceptInCSharp/Program.cs +++ b/csharp-linq/UsingExceptInCSharp/UsingExceptInCSharp/Program.cs @@ -1,2 +1,11 @@ -// See https://aka.ms/new-console-template for more information -Console.WriteLine("Hello, World!"); +using UsingExceptInCSharp; + +var examples = new ExceptMethodExamples(); + +Console.WriteLine(string.Join(", ", examples.GetDistinctDifference())); +Console.WriteLine(examples.GetEmployeesNotInSales().Count); +Console.WriteLine(examples.GetEmployeesNotInSalesFromCopies().Count); +Console.WriteLine(examples.GetEmployeesNotInSalesUsingComparer().Count); +Console.WriteLine(string.Join(", ", examples.GetEmployeeRecordsNotInSales().Select(e => e.Name))); +Console.WriteLine(string.Join(", ", examples.GetEmployeesNotInITIgnoreCase())); +Console.WriteLine(string.Join(", ", examples.GetEmployeesNotInITByID().Select(e => e.Name))); diff --git a/csharp-linq/UsingExceptInCSharp/UsingExceptInCSharp/UsingExceptInCSharp.csproj b/csharp-linq/UsingExceptInCSharp/UsingExceptInCSharp/UsingExceptInCSharp.csproj index 2150e3797b..ed9781c223 100644 --- a/csharp-linq/UsingExceptInCSharp/UsingExceptInCSharp/UsingExceptInCSharp.csproj +++ b/csharp-linq/UsingExceptInCSharp/UsingExceptInCSharp/UsingExceptInCSharp.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net10.0 enable enable diff --git a/csharp-linq/UsingExceptInCSharp/UsingExceptInCSharpTests/UsingExceptInCSharpTests.csproj b/csharp-linq/UsingExceptInCSharp/UsingExceptInCSharpTests/UsingExceptInCSharpTests.csproj index fcd2168885..f654b0bd11 100644 --- a/csharp-linq/UsingExceptInCSharp/UsingExceptInCSharpTests/UsingExceptInCSharpTests.csproj +++ b/csharp-linq/UsingExceptInCSharp/UsingExceptInCSharpTests/UsingExceptInCSharpTests.csproj @@ -1,7 +1,7 @@ - net8.0 + net10.0 enable enable @@ -10,10 +10,10 @@ - - - - + + + + diff --git a/csharp-linq/UsingExceptInCSharp/UsingExceptInCSharpTests/UsingExceptUnitTests.cs b/csharp-linq/UsingExceptInCSharp/UsingExceptInCSharpTests/UsingExceptUnitTests.cs index 63547073fb..8fcd4e2b07 100644 --- a/csharp-linq/UsingExceptInCSharp/UsingExceptInCSharpTests/UsingExceptUnitTests.cs +++ b/csharp-linq/UsingExceptInCSharp/UsingExceptInCSharpTests/UsingExceptUnitTests.cs @@ -16,10 +16,27 @@ public void GivenAllEmployees_WhenExceptInvoked_ThenVerifyThatNoSalesEmployeesRe var sheilaRecord = nonSales.Find(i => i.Name == "Sheila Foxx"); Assert.IsInstanceOfType(nonSales, typeof(List)); + Assert.HasCount(8, nonSales); Assert.IsNull(maryRecord); Assert.IsNotNull(sheilaRecord); } + [TestMethod] + public void GivenDuplicatesInFirstSequence_WhenExceptInvoked_ThenVerifyThatResultIsDistinct() + { + var result = _examples.GetDistinctDifference(); + + CollectionAssert.AreEqual(new List { 1, 2, 4 }, result); + } + + [TestMethod] + public void GivenCopiesOfSalesEmployees_WhenExceptInvokedWithoutComparer_ThenVerifyThatNothingIsRemoved() + { + var result = _examples.GetEmployeesNotInSalesFromCopies(); + + Assert.HasCount(12, result); + } + [TestMethod] public void GivenAllEmployees_WhenExceptInvokedIgnoreCase_ThenVerifyThatNoITEmployeesReturned() { @@ -27,18 +44,18 @@ public void GivenAllEmployees_WhenExceptInvokedIgnoreCase_ThenVerifyThatNoITEmpl Assert.IsNotNull(nonIT); Assert.IsInstanceOfType(nonIT, typeof(List)); - Assert.IsFalse(nonIT.Contains("ava knowles")); - Assert.IsFalse(nonIT.Contains("grace jones")); + Assert.HasCount(10, nonIT); + Assert.DoesNotContain("Ava Knowles", nonIT); + Assert.DoesNotContain("Grace Jones", nonIT); } [TestMethod] - [ExpectedException(typeof(ArgumentNullException))] public void GivenAllEmployees_WhenExceptInvokedAgainstNull_ThenVerifyThatExceptionThrown() { var numbers = new List { 1, 2, 3, 4 }; - List emptyList = null; + List? nullList = null; - var result = numbers.Except(emptyList); + Assert.ThrowsExactly(() => numbers.Except(nullList!)); } [TestMethod] @@ -50,7 +67,26 @@ public void GivenAllEmployees_WhenExceptInvoked_ThenVerifyThatNoSalesEmployeesRe var comparison = _employeeComparer.Equals(expectedRecord, sheilaRecord); Assert.IsInstanceOfType(nonSales, typeof(List)); + Assert.HasCount(8, nonSales); Assert.IsTrue(comparison); Assert.IsNotNull(sheilaRecord); } -} \ No newline at end of file + + [TestMethod] + public void GivenRecords_WhenExceptInvokedWithoutComparer_ThenVerifyThatValueEqualityIsUsed() + { + var result = _examples.GetEmployeeRecordsNotInSales(); + + CollectionAssert.AreEqual(new List { "Sheila Foxx", "Grace Jones" }, result.Select(e => e.Name).ToList()); + } + + [TestMethod] + public void GivenITEmployeeIDs_WhenExceptByInvoked_ThenVerifyThatNoITEmployeesReturned() + { + var result = _examples.GetEmployeesNotInITByID(); + + Assert.HasCount(10, result); + Assert.IsNull(result.Find(e => e.ID == 6)); + Assert.IsNull(result.Find(e => e.ID == 7)); + } +}