2012-02-14 10 views
9

Al trabajar con la clase List de System.Collections.Generic, los métodos como Contains o IndexOf compararán el objeto de referencia pasado utilizando el método Equals implementado desde IEquatable, o el método Equals reemplazado proporcionado por la clase Object. Si Object.Equals no se reemplaza, comprobará si la referencia aprobada apunta al mismo objeto que él.Comparar por referencia?

Mi pregunta es: ¿Hay alguna manera de hacer que la Lista se compare por referencia si se anula Igual? El código siguiente se eliminará el elemento de la lista:

class Program 
{ 
    static void Main(string[] args) 
    {  
     var s1 = new SomeClass() { A = 5 }; 
     var s2 = new SomeClass() { A = 5 }; 
     var list = new List<SomeClass>(); 
     list.Add(s1); 
     list.Remove(s2); // s1 will get removed, even though s2 has been 
         // passed, because s1's Equals method will return true. 

    } 
} 

class SomeClass 
{ 
    public int A { get; set; } 

    public override bool Equals(object obj) 
    { 
     SomeClass s = obj as SomeClass; 
     if (s == null) 
     { 
      return false; 
     } 
     else 
     { 
      return s.A == this.A; 
     } 
    } 
} 

Digamos que soy incapaz de eliminar la aplicación de Iguales SomeClass', hay una manera de hacer la lista de comparación por referencia en lugar del valor?

Respuesta

13

Puede usar List.RemoveAll y en su predicado, compare los artículos con Object.ReferenceEquals.

list.RemoveAll(item => object.ReferenceEquals(item, s2)); 

El código eliminó correctamente los 1 elementos al depurar desde Visual Studio 2010 Express.

+0

Gracias, eso parece funcionar bien. – haiyyu

4

La solución de Austin es simple y funciona. Pero aquí hay dos métodos de extensión genéricos también:

items.RemoveAllByReference(item); 

public static void RemoveAllByReference<T>(this List<T> list, T item) 
{ 
    list.RemoveAll(x=> object.ReferenceEquals(x, item)); 
} 

public static bool RemoveFirstByReference<T>(this List<T> list, T item) 
{ 
    var index = -1; 
    for(int i = 0; i< list.Count; i++) 
     if(object.ReferenceEquals(list[i], item)) 
     { 
      index = i; 
      break; 
     } 
    if(index == -1) 
     return false; 

    list.RemoveAt(index); 
    return true; 
} 
+0

Interesante, pero ¿por qué es esto más óptimo? ¿No es esto similar a lo que hace el predicado internamente? Simplemente para saber su razonamiento ... –

+0

¿Qué pasa si el artículo está en la lista n veces? –

+0

El método de Austin siempre verifica todos los elementos. Éste rompe el ciclo cuando encuentra uno. Pero ahora que lo pienso, puede ser más correcto buscar en toda la lista y eliminar todas las instancias del mismo elemento en una lista ... Por lo tanto, depende de lo que desee. Pero aún así, un método de extensión es una ventaja si lo usa en varios lugares. – doblak