2010-09-02 14 views
8

Tengo una función que debe invocarse si una lista ha cambiado desde la última vez que se llamó, ¿cuál sería la mejor manera de implementar esto?Método que requiere menos CPU para verificar si una lista ha cambiado en C#

ejemplo:

List<A> OurList = new List<A>(); 
private void Update() 
{ 
    Boolean Changed = //?  
    if(Changed) CheckList(OurList); 
} 

habría dado por hecho que una variable para almacenar la lista de edad y comparar, pero ¿cómo actualizar la lista antigua a la nueva lista sin copiar todo hacia fuera? (Si hago una asignación, también actualizará la "lista anterior")

Respuesta

13

La forma más eficiente sería ajustar el List<> en su propia clase y tener todos los métodos de mutación (Agregar, Eliminar) establecer una bandera booleana .

Su método puede simplemente mirar esa bandera y restablecerla.

+3

También podría haber algún tipo de evento - sistema de escucha que notifica a las partes interesadas cuando la colección ha cambiado. – Carlos

+0

Esto suena como la mejor manera, creo que sería mucho más fácil tener una colección personalizada para algunas cosas para las que actualmente estoy usando la lista. Gracias :) – Blam

1
  • Restringir el acceso a la lista.
  • Permitir cambios solo a través de una API prescrita.
  • En esa API, establezca un indicador siempre que se llame al método ChangeList.
1

¿Está tratando de ver si la Lista misma cambió (agregando/quitando elementos), o si un elemento de la lista ha cambiado?

Si simplemente está buscando ver si una lista tiene un elemento agregado/quitado, lo más fácil sería envolver la Lista en una nueva clase y anular los métodos Agregar/Quitar para que su objeto active un booleano.

El requisito más complicado es si necesita saber si un elemento contenido en la lista ha cambiado (una propiedad o campo en el objeto de clase al que se hace referencia en la lista). Si ese es el caso, depende de su situación específica. Podría poner en el setter las propiedades de esas clases una forma de activar un booleano que haría lo mismo que antes. Pero esto depende de la complejidad de la clase en la lista genérica.

5

Si está utilizando .NET 4.0, podría usar la clase ObservableCollection. (antes de 4.0, necesitaría hacer referencia a WPF).

Una vez que haya creado su lista, simplemente agregue un controlador al evento CollectionChanged.

+0

La referencia de WPF no es ideal y tener .NET 3.5 es un requisito, pero gracias de todos modos :) – Blam

19

Utilice un ObservableCollection<T> en lugar de una lista, luego suscríbase al evento CollectionChanged.

De esta manera, se le informará cuándo se cambia la lista en lugar de tener que escanear los datos para descubrir qué sucedió después del hecho.

+0

creemos igual y en un marco de tiempo similar. Alrededor de un minuto y medio diferente. – Robaticus

+3

+1: ¿Por qué enrollarte cuando hay una implementación perfectamente buena disponible? Consulte también [NotifyCollectionChangedEventArgs] (http://msdn.microsoft.com/en-us/library/system.collections.specialized.notifycollectionchangedeventargs_members.aspx). –

+0

en .Net 3.5, pero gracias de todos modos :) – Blam

2

Su mejor opción sería utilizar un ObservableCollection<T> o BindingList<T> para recibir la notificación push de un cambio. También puede crear la subclase Collection<T> si desea un comportamiento personalizado.

Para responder a su pregunta tal como se solicitó (excepto para el bit de CPU intensiva), puede usar una función existente de List<T>: mantiene su propia versión internamente para que pueda lanzarse si la colección ha cambiado durante la enumeración.

Esto se basa en el análisis del código del reflector. No forma parte de ningún contrato, por lo que es probable que se rompa en cualquier momento. También puede no funcionar en un entorno de confianza parcial.Por favor, use con cuidado:

public static int GetVersion<T>(this List<T> list) 
{ 
    return (int)list.GetType() 
        .GetField("_version", BindingFlags.Instance | BindingFlags.NonPublic) 
        .GetValue(list); 
} 

... 

private int _lastCheckedVersion = 0; 

private void Update() 
{ 
    int currentVersion = ourList.GetVersion(); 

    if(currentVersion != _lastCheckedVersion) CheckList(ourList); 

    _lastCheckedVersion = currentVersion; 
} 
Cuestiones relacionadas