how - list findindex c# example
¿Qué usa Collection.Contains() para verificar si hay objetos existentes? (6)
Primero defina la clase de ayuda con IEqualityComparer.
public class MyEqualityComparer<T> : IEqualityComparer<T>
{
Func<T, int> _hashDelegate;
public MyEqualityComparer(Func<T, int> hashDelegate)
{
_hashDelegate = hashDelegate;
}
public bool Equals(T x, T y)
{
return _hashDelegate(x) == _hashDelegate(y);
}
public int GetHashCode(T obj)
{
return _hashDelegate(obj);
}
}
Luego, en su código, simplemente defina el comparador y úselo:
var myComparer = new MyEqualityComparer<MyObject>(delegate(MyObject obj){
return obj.ID;
});
var result = collection
.Where(f => anotherCollection.Contains(f.First, myComparer))
.ToArray();
De esta forma, puede definir la forma en que se calcula la igualdad sin modificar sus clases. También puede usarlo para procesar objetos de bibliotecas de terceros ya que no puede modificar su código.
Tengo una lista fuertemente tipada de objetos personalizados, MyObject, que tiene un Id de propiedad junto con algunas otras propiedades.
Digamos que Id de MyObject lo define como único y quiero verificar si mi colección aún no tiene un objeto MyObject que tenga Id de 1 antes de agregar mi nuevo MyObject a la colección.
Quiero usar if (! List.Contains (myObj)) pero, ¿cómo puedo hacer que el hecho de que solo una o dos propiedades de MyObject lo definan como único?
Puedo usar IComparable? ¿O solo tengo que anular el método Equals pero necesitaría heredar algo primero? ¿Es así?
Gracias
Puede anular Equals y GetHashCode, implementar un IEqualityComparer<MyObject>
y usarlo en la llamada Contains
, o usar un método de extensión como Any
if (!myList.Any(obj => obj.Property == obj2.Property && obj.Property2 == obj2.Property2))
myList.Add(obj2);
Puede usar LINQ para hacer esto con bastante facilidad.
var result = MyCollection.Any(p=>p.myId == Id);
if(result)
{
//something
}
Puedes usar IEquatable<T>
. Implemente esto en su clase, y luego verifique si el T pasado a Equals tiene el mismo ID que este. Id. Estoy seguro de que esto funciona para verificar una clave en un diccionario, pero no la he usado para una colección.
List<T>.Contains
utiliza EqualityComparer<T>.Default
, que a su vez usa IEquatable<T>
si el tipo lo implementa u object.Equals
. De lo contrario.
Puede implementar IEquatable<T>
pero es una buena idea anular object.Equals
si lo hace, y una muy buena idea para reemplazar GetHashCode()
si hace eso:
public class SomeIDdClass : IEquatable<SomeIDdClass>
{
private readonly int _id;
public SomeIDdClass(int id)
{
_id = id;
}
public int Id
{
get { return _id; }
}
public bool Equals(SomeIDdClass other)
{
return null != other && _id == other._id;
}
public override bool Equals(object obj)
{
return Equals(obj as SomeIDdClass);
}
public override int GetHashCode()
{
return _id;
}
}
Tenga en cuenta que el código hash se relaciona con los criterios de igualdad. Esto es vital.
Esto también lo hace aplicable para cualquier otro caso en el que la igualdad, definida por tener el mismo ID, sea útil. Si tiene uno de los requisitos para verificar si una lista tiene tal objeto, entonces probablemente sugeriría simplemente hacerlo:
return someList.Any(item => item.Id == cmpItem.Id);
List<T>
usa el comparador devuelto por EqualityComparer<T>.Default
y de acuerdo con la documentation para eso:
La propiedad Default comprueba si el tipo T implementa la interfaz System.IEquatable (Of T) y, si es así, devuelve un EqualityComparer (Of T) que usa esa implementación. De lo contrario, devuelve un EqualityComparer (Of T) que usa las anulaciones de Object.Equals y Object.GetHashCode proporcionadas por T.
Entonces puede implementar IEquatable<T>
en su clase personalizada o anular los métodos Equals
(y GetHashCode
) para hacer la comparación por las propiedades que necesita. Alternativamente, podrías usar linq:
bool contains = list.Any(i => i.Id == obj.Id);