2010-10-01 17 views
6

Quiero saber si el valor de cualquiera de los campos privados o públicos ha cambiado. ¿Hay alguna otra manera que no sea over the riding GetHashCode() o calcular CRC?C# La forma más rápida de saber algo en el objeto ha cambiado?

El algoritmo debe ser rápido también.

Gracias,

-Brajesh

+6

GetHashCode no es útil para determinar si un caso dado ha cambiado, que está relacionado con la identidad de la instancia y por lo tanto debe atributos único caso hash que están realmente relacionado con identiy, no todos y cada valor en tu instancia. –

+2

¿Tiene el código fuente para el tipo en cuestión o tiene que funcionar en tipos arbitrarios? –

Respuesta

5

Normalmente, esto se haría con la interfaz INotifyPropertyChanged (link). Sin embargo, en realidad solo es práctico usarlo con propiedades, no con campos. Sin embargo, puedes crear una propiedad privada para cada uno de tus campos privados. Una vez que tenga todo como una propiedad, edite el setter para que verifique si el valor ha cambiado, luego llame al NotifyPropertyChanged() si lo tiene.

Ejemplo:

public event PropertyChangedEventHandler PropertyChanged; 

private int _foo; 

public int Foo 
{ 
    get { return _foo; } 
    set 
    { 
     if (_foo != value) 
     { 
      _foo = value; 
      NotifyPropertyChanged("Foo"); 
     } 
    } 
} 

private void NotifyPropertyChanged(string info) 
{ 
    if (PropertyChanged != null) 
    { 
     PropertyChanged(this, new PropertyChangedEventArgs(info)); 
    } 
} 
2

Es posible que desee encapsular todos sus datos (que desea supervisar para el cambio) dentro de los descriptores de acceso get/set (propiedades alias).

Entonces, en el conjunto de acceso, compruebe si el valor ha cambiado, ponerlo en valor nuevo, y:

  • conjunto _dirty true (si es necesario verificarlo más tarde)

o

  • aumento algún evento a su gusto

Algunas notas sobre CRC: incluso si tiene un algoritmo CRC/HASH que no colisiona para su objeto, debe tener hash original en algún lugar. Pero es probable que los hash simples se dupliquen, por lo que nuevamente tienes problemas de velocidad.

1

Si necesita funcionar para cualquier tipo y necesita detectar cualquier modificación, sin falsos negativos ni falsos positivos, no veo mejor manera que una copia de todos los valores de campo para referencia. Ya que se necesita que sea rápido, recomiendo lo siguiente:

  1. escribir una rutina que utiliza la reflexión para realizar una copia superficial de todos los valores de campo.

  2. escribir una rutina que compara los campos de valor (si usted está en busca de cambios en las estructuras anidadas, como matrices o colecciones, su problema es mucho más difícil.)

  3. vez que el trabajo anterior, se puede use IL Emit y escriba el código que hace la Reflexión una vez y emite el código para las operaciones de copia superficial y de comparación. Ahora tiene algunas instancias de DynamicMethod que puede usar para cada operación. Estos son bastante rápidos, una vez emitidos y jitted.

1

Insertar en cada colocador pública un valor booleano, como m_IsChanged, a continuación, utilizando un captador público sólo para comprobar si una de las propiedades ha cambiado.

Ejemplo:

private bool m_IsChanged = false; 

private double m_DoubleValue; 

//[...] all other private properties 

public double DoubleValue 
{ 
    get { return m_DoubleValue; } 
    set 
    { 
     if(m_DoubleValue != value) 
      m_IsChanged = true; 

     m_DoubleValue = value; 
    } 
} 

//[...] all other getters/setters 

public bool IsChanged 
{ 
    get { return m_IsChanged; } 
} 
Cuestiones relacionadas