Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

222
Views
Cómo comparar registros que contienen colecciones de registros sin implementar comparaciones de igualdad

C# 9 introduce registros que, entre otros beneficios, permiten una comparación realmente sencilla. ¿Hay alguna forma en que pueda aprovechar esa funcionalidad para comparar un registro compuesto por una colección de otros registros?

Por ejemplo:

 record Foo { string Name {get; set;} List<Bar> Bars {get; set;} public Foo(string name, params int[] values) { Name = name; Bars = values.Select(v => new Bar(v)).ToList(); } } record Bar { int Value {get; set;} public Bar(int value) => Value = value; }

En otro lugar del código:

 var foo1 = new Foo("Hi",1,2,3); var foo2 = new Foo("Hi",1,2,3); return foo1 == foo2; // I want this to return true

Por cierto, no estoy buscando una solución para este código específico. Sé que puedo anular el operador == o implementar IComparable<Foo> , etc. Mi objetivo es aprovechar la funcionalidad integrada para no tener que implementar mis propios métodos cada vez que quiero comparar un contenedor de datos compuesto por una colección de contenedores de datos. ¿Hay una manera de hacer eso?

¡Gracias!

over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

Desafortunadamente, no hay una forma "agradable" de hacer lo que quieres. Por lo general, tiene una de dos opciones:

  • Implemente manualmente la igualdad para su registro, en este caso usando SequenceEqual para la lista, o
  • solo use clases que tengan semántica de valor.

Para lo último, puede escribir una clase contenedora para la lista, por ejemplo, como se describe en esta respuesta a "tipos de registro con propiedades de colección y colecciones con semántica de valor" , y luego solo use esa clase en sus registros.

over 4 years ago · Santiago Trujillo Report

0

De hecho, encontré una buena solución. Puede extender List<T> para anular Equals y GetHashCode

 public class ValueEqualityList<T>:List<T> { private readonly bool _requireMathcingOrder; public ValueEqualityList(bool requireMatchingOrder = false) => _requireMathcingOrder = requireMatchingOrder; public override bool Equals(object other) { if (!(other is IEnumerable<T> enumerable)) return false; if(!_requireMathcingOrder)return enumerable.ScrambledEquals(this); return enumerable.SequenceEqual(this); } public override int GetHashCode() { var hashCode = 0; foreach (var item in this) { hashCode ^= item.GetHashCode(); } return hashCode; } }

Foo se convierte en:

 record Foo { string Name {get; set;} List<Bar> Bars {get; set;} public Foo(string name, params int[] values) { Name = name; //this is the line that changed Bars = new ValueEqualityList<Bar>(values.Select(v => new Bar(v))); } }

Esto usa algún código de ayuda:

 static class EnumerableExtensions { /// <summary> /// Returns true if both enumerables contain the same items, regardless of order. O(N*Log(N)) /// </summary> /// <typeparam name="T"></typeparam> /// <param name="first"></param> /// <param name="second"></param> /// <returns></returns> public static bool ScrambledEquals<T>(this IEnumerable<T> first, IEnumerable<T> second) { var counts = first.GetCounts(); foreach (var item in second) { if (!counts.TryGetValue(item, out var count)) return false; count -= 1; counts[item] = count; if (count < 0) return false; } return counts.Values.All(c => c == 0); } public static Dictionary<T, int> GetCounts<T>(this IEnumerable<T> enumerable) { var counts = new Dictionary<T, int>(); foreach (var item in enumerable) { if (!counts.TryGetValue(item, out var count)) { count = 0; } count++; counts[item] = count; } return counts; } }
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!