c#, отмечающий свойство класса как грязное

На самом деле, я решил проблему в ближайшее время, поэтому я отвечу на мой вопрос.

Решение:

Id = test['PassengerId']
pred = vc.predict(X_test)

output = pd.concat([pd.DataFrame(Id), pd.DataFrame(pred)], axis=1)

output.to_csv('~/Documents/Titanic/submission.csv', index=False, header=True)

Приветствия.

24
задан 30 April 2009 в 05:56
поделиться

8 ответов

Один из вариантов - изменить его при записи; Другой способ - сохранить копию всех исходных значений и вычислить степень загрязненности, когда кто-нибудь об этом попросит. Это дает дополнительное преимущество, заключающееся в том, что вы можете точно сказать , какие поля изменились (и каким образом), что означает, что вы можете выдавать минимальные операторы обновления и немного упростить разрешение конфликтов слияния.

Вы также можете поставить вся проверка на грязность в одном месте, чтобы она не загрязняла остальную часть вашего кода.

Я не говорю, что он идеален, но этот вариант стоит рассмотреть.

23
ответ дан 28 November 2019 в 22:16
поделиться

Если ваш Example_Class является легковесным, рассмотрите возможность сохранения исходного состояния и последующего сравнения текущего состояния с исходным, чтобы определить изменения. Если нет, то ваш подход - лучший, потому что в этом случае очистка исходного состояния потребляет много системных ресурсов.

1
ответ дан 28 November 2019 в 22:16
поделиться

Ваш подход в основном такой, как я бы это сделал. Я бы просто удалите установщик для свойства Status:

public StatusEnum Status
{
    get { return _Status; }
    // set { _Status = value; }
}

и вместо этого добавьте функцию

public SetStatusClean()
{
    _Status = StatusEnum.Clean;
}

, а также SetStatusDeleted () и SetStatusPurged () , потому что я считаю, что это лучше указывает намерение .

Редактировать

Прочитав ответ Джона Скита , мне нужно пересмотреть свой подход ;-) Для простых объектов я бы придерживался своего пути, но если он станет более сложным, его предложение приведет к гораздо лучше организованному коду.

1
ответ дан 28 November 2019 в 22:16
поделиться

Если вы действительно хотите использовать флаг грязного уровня на уровне класса (или, в этом отношении, уведомления) - вы можете использовать приемы, подобные приведенным ниже, чтобы минимизировать беспорядок в ваших свойствах (здесь показаны оба IsDirty и PropertyChanged , просто для удовольствия).

Очевидно, что использовать перечислимый подход - тривиальный вопрос (единственная причина, по которой я этого не сделал, - сохранить простой пример):

class SomeType : INotifyPropertyChanged {
    private int foo;
    public int Foo {
        get { return foo; }
        set { SetField(ref foo, value, "Foo"); }
    }

    private string bar;
    public string Bar {
        get { return bar; }
        set { SetField(ref bar, value, "Bar"); }
    }

    public bool IsDirty { get; private set; }
    public event PropertyChangedEventHandler PropertyChanged;
    protected void SetField<T>(ref T field, T value, string propertyName) {
        if (!EqualityComparer<T>.Default.Equals(field, value)) {
            field = value;
            IsDirty = true;
            OnPropertyChanged(propertyName);
        }
    }
    protected virtual void OnPropertyChanged(string propertyName) {
        var handler = PropertyChanged;
        if (handler != null) {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Вы также можете добавить часть этого в абстрактный базовый класс, но это отдельное обсуждение

39
ответ дан 28 November 2019 в 22:16
поделиться

Посмотрите на PostSharp ( http://www.postsharp.org/ ). Вы можете легко создать атрибут, который помечает его как грязный, вы можете добавить атрибут к каждому свойству, которое нуждается в нем, и он хранит весь ваш код в одном месте.

Грубо говоря, создайте интерфейс, который имеет ваш статус, чтобы класс реализовывал его. , Создайте атрибут, который можно применить к свойствам и привести к вашему интерфейсу, чтобы установить значение при изменении одного из отмеченных свойств.

3
ответ дан 28 November 2019 в 22:16
поделиться

Если вы хотите реализовать его таким образом и хотите уменьшить объем кода, вы можете рассмотреть применение Аспектно-ориентированного программирования.

Например, вы можете использовать время компиляции как ткач PostSharp , и создайте «аспект», который можно применить к свойствам. Этот аспект затем гарантирует, что ваш грязный флаг установлен, когда это необходимо.

Аспект может выглядеть следующим образом:

[Serializable]
[AttributeUsage(AttributeTargets.Property)]
public class ChangeTrackingAttribute : OnMethodInvocationAspect
{
    public override void OnInvocation( MethodInvocationEventArgs e )
    {
        if( e.Delegate.Method.ReturnParameter.ParameterType == typeof(void) )
        {
              // we're in the setter
              IChangeTrackable target = e.Delegate.Target as IChangeTrackable;

              // Implement some logic to retrieve the current value of 
              // the property
              if( currentValue != e.GetArgumentArray()[0] )
              {
                  target.Status = Status.Dirty;
              }
              base.OnInvocation (e);
        } 
    }  
} 

Offcourse, это означает, что классы, для которых вы хотите реализовать ChangeTracking, должны реализовывать IChangeTrackable интерфейс (пользовательский интерфейс), который имеет по крайней мере свойство 'Status'.

Вы также можете создать пользовательский атрибут ChangeTrackingProperty и убедиться, что аспект, который был создан выше, Вы даже можете убедиться, что PostSharp проверяет во время компиляции, реализуют ли классы, свойства которых украшены атрибутом ChangeTrackingProperty, интерфейс IChangeTrackable.

16
ответ дан 28 November 2019 в 22:16
поделиться

Помимо совета 'подумайте над тем, чтобы сделать ваш тип неизменным', вот кое-что, что я написал (и заставил Джона и Марка научить меня чему-то по пути)

public class Example_Class
{    // snip
     // all properties are public get and private set

     private Dictionary<string, Delegate> m_PropertySetterMap;

     public Example_Class()
     {
        m_PropertySetterMap = new Dictionary<string, Delegate>();
        InitializeSettableProperties();
     }
     public Example_Class(long id, string name):this()
     {   this.ID = id;    this.Name = name;   }

     private void InitializeSettableProperties()
     {
        AddToPropertyMap<long>("ID",  value => { this.ID = value; });
        AddToPropertyMap<string>("Name", value => { this.Name = value; }); 
     }
     // jump thru a hoop because it won't let me cast an anonymous method to an Action<T>/Delegate
     private void AddToPropertyMap<T>(string sPropertyName, Action<T> setterAction)
     {   m_PropertySetterMap.Add(sPropertyName, setterAction);            }

     public void SetProperty<T>(string propertyName, T value)
     {
        (m_PropertySetterMap[propertyName] as Action<T>).Invoke(value);
        this.Status = StatusEnum.Dirty;
     }
  }

Вы понимаете идею. Возможные улучшения: Используйте константы для PropertyNames и проверьте, действительно ли свойство изменилось. Один из недостатков заключается в том, что

obj.SetProperty("ID", 700);         // will blow up int instead of long
obj.SetProperty<long>("ID", 700);   // be explicit or use 700L
1
ответ дан 28 November 2019 в 22:16
поделиться

Другой метод заключается в том, чтобы переопределить метод GetHashCode () примерно так:

public override int GetHashCode() // or call it GetChangeHash or somthing if you dont want to override the GetHashCode function...
{
    var sb = new System.Text.StringBuilder();

    sb.Append(_dateOfBirth);
    sb.Append(_marital);
    sb.Append(_gender);
    sb.Append(_notes);
    sb.Append(_firstName);
    sb.Append(_lastName);  

    return sb.ToString.GetHashCode();
}

После загрузки из базы данных получите хеш-код объекта. Затем перед сохранением проверьте, равен ли текущий хеш-код предыдущему хеш-коду. если они одинаковые, не сохраняйте.

Редактировать:

Как указали люди, это приводит к изменению хеш-кода - поскольку я использую Guids для идентификации своих объектов, я не против, если хеш-код изменяется .

Edit2:

Поскольку люди не хотят изменять хэш-код, вместо того, чтобы переопределять метод GetHashCode, просто вызовите метод как-нибудь еще. Смысл заключается в обнаружении изменений, а не в том, использую ли я для идентификации объектов направляющие или хэш-коды.

-1
ответ дан 28 November 2019 в 22:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: