我有一个大项目,我即将在发布模式下进行首次测试,但发现了一个大问题。此代码查找当前可见列表中但不在数据库中的所有对象,并将它们添加到另一个列表中以供以后删除。通常,如果没有差异,toRemove将保持为空。但是在发布模式下,没有差异时,toRemove会填充整个visibleList

// Find which elements are in the visible list that do not exist in the database
foreach(var tr in visibleList.Where((entry) =>
   {
       return fullList.Contains(entry);
   }))
{
   toRemove.Add(tr);
}


拆解代码并运行一些测试之后,我将问题缩小到了这个范围:

// Returns true in DEBUG mode, but false in RELEASE mode
//  (when entry does in fact equal fullList[0])
bool equalityResult = entry.Equals(fullList[0]);


fullListtoRemove只是基本的C#List<Entry>对象,而visibleListObservableCollection<Entry>

Entry.Equals没有过载。

为什么两个配置之间的功能会有所不同?我该怎么做才能解决此问题?

编辑:Entry定义的大部分是:

public class Entry : INotifyPropertyChanged
{
    public String Name { get; set; }
    public String Machine { get; set; }
    public Int32 Value { get; set; }

    // Output values separated by a tab.
    public override string ToString()
    {
        return String.Format("{0}\t{1}\t{2}", Name, Machine, Value);
    }

    public String ToCSVString()
    {
        return String.Format("{0},{1},{2}", Name, Machine, Value);
    }

    #region WPF Functionality
    // Enable one-way binding in WPF
    public event PropertyChangedEventHandler PropertyChanged;
    protected void NotifyPropertyChanged(string name)
    {
        PropertyChangedEventHandler h = PropertyChanged;
        if (h != null)
        {
            h(this, new PropertyChangedEventArgs(name));
        }
    }
    #endregion

    // ...
}


编辑:我实现了Entry.Equals,并解决了问题。事实证明,在导致代码中的Entry.Equals更改从发行版本中排除的所有问题上,我都有一些链接错误。修复此问题并实现Equals后,所有内容都会像魅力一样起作用。我不得不不得不重写该方法,这让我感到很难过,似乎工作量太大。

最佳答案

如果尚未在Equals类中定义Entry实现,则假定它是一个类而不是结构,默认情况下Equals仅执行引用比较。见What is the default behavior of Equals Method?

例如:

public class AgeWrapper {
    public int Age { get; set; }
    public AgeWrapper( int age ) { this.Age = age; }
}

public void DoWork() {
   AgeWrapper a = new AgeWrapper(21);
   AgeWrapper b = new AgeWrapper(21);
   AgeWrapper c = a;

   Console.WriteLine( a.Equals(b) ); // prints false;

   Console.WriteLine( a.Equals(c) ); // prints true;
}


使之按您期望的方式工作的唯一方法是提供您自己的Equals比较。

并且由于您将执行此操作,因此您将需要重写GetHashCode,以便两者生成一致的值。神奇的Jon Skeet可以帮助您the proper way做到这一点。

您不希望ReferenceEquals-您关心的是对象中包含的值,而不是它们存储在内存中的位置。

public class Entry : INotifyPropertyChanged
{
    public String Name { get; set; }
    public String Machine { get; set; }
    public Int32 Value { get; set; }

    public override bool Equals( object other )
    {
        Entry otherEntry = other as Entry;

        if ( otherEntry == null ) { return false; }

        return
            otherEntry.Name.Equals( this.Name ) &&
            otherEntry.Machine.Equals( this.Machine ) &&
            otherEntry.Value.Equals( this.Value );
     }


     public override int GetHashCode()
     {
          // Thanks Jon Skeet!
          unchecked // Overflow is fine, just wrap
          {
              int hash = (int) 2166136261;

              hash = hash * 16777619 ^ this.Name.GetHashCode();
              hash = hash * 16777619 ^ this.Machine.GetHashCode();
              hash = hash * 16777619 ^ this.Value.GetHashCode();

              return hash;
          }
     }
}


上面假设NameMachineValue定义了对象的身份。

07-28 02:55
查看更多