0
private readonly Dictionary<ExcelCellIdentifier, int> allInfoByIdentifier = new Dictionary<ExcelCellIdentifier, int>();

public class ExcelCellIdentifier
{
    public ExcelCellIdentifier(string ticker, string identifier)
    {
        Ticker = ticker;
        Identifier = identifier;
    }
    public string Ticker { get; set; }
    public string Identifier { get; set; }
}

然后在某个时候,我想通过创建一个具有相同代码和标识符的 ExcelCellIdentifier 对象来搜索 int,例如:

ExcelCellIdentifier ex = new ExcelCellIdentifier("Ticker1", "Identifier1");
int a = allInfoByIdentifier[ex];
//a is a value stored before hand

这可能吗?

4

4 回答 4

3

文档中:

Dictionary<TKey, TValue>需要一个相等实现来确定键是否相等。您可以IEqualityComparer<T>使用接受比较器参数的构造函数来指定通用接口的实现;如果您不指定实现,则使用默认的泛型相等比较器EqualityComparer<T>.Default。如果类型TKey实现了System.IEquatable<T>泛型接口,则默认相等比较器使用该实现。

在这种情况下,由您决定希望相等性如何工作 - 在构造字典时提供比较器或实现IEquatable<T>. 中间选项对您不起作用,因为引用类型的默认比较器使用引用相等。

于 2013-07-16T14:18:00.593 回答
1

是的,只要你IEquatable<ExcelCellIdentifier>在你的ExcelCellIdentifier类中实现,或者用IEqualityComparer<ExcelCellIdentifier>.

要记住的一件重要的事情是,尽管我认为不会IEquatable<T>强迫您覆盖GetHashCode()(尽管如下所述,它是文档中强制要求的),但您需要确保适当地覆盖它,否则即使您的对象返回 true for Equals(), one不能作为在字典中查找另一个的键。

这是一个有趣的调试的原因,你确定你的相等比较器工作正常,但不知何故你的字典没有检索任何东西!

为了我的钱,我更喜欢实现一个自定义相等比较器,它将管理字典的业务与类的实现分开:

    private readonly Dictionary<ExcelCellIdentifier, int> allInfoByIdentifier =
        new Dictionary<ExcelCellIdentifier, int>(new ExcelCellIdentifierComparer());

    public class ExcelCellIdentifier
    {
        private ExcelCellIdentifier(string ticker, string identifier)
        {
            Ticker = ticker;
            Identifier = identifier;
        }

        public string Ticker { get; set; }

        public string Identifier { get; set; }

    }

    private class ExcelCellIdentifierComparer : IEqualityComparer<ExcelCellIdentifier>
    {
        public bool Equals(ExcelCellIdentifier x, ExcelCellIdentifier y)
        {
            return x.Identifier == y.Identifier && x.Ticker == y.Ticker;
        }

        public int GetHashCode(ExcelCellIdentifier obj)
        {
            return obj.Identifier.GetHashCode() ^ obj.Ticker.GetHashCode();
        }
    }
于 2013-07-16T14:19:00.463 回答
1

因为没有其他人使用 IEquateable 给你一个合适的版本,你去吧

public class ExcelCellIdentifier : IEquatable<ExcelCellIdentifier>
{
   public ExcelCellIdentifier(string ticker, string identifier)
   {
        Ticker = ticker;
        Identifier = identifier;
   }

   public override bool Equals(object obj)
   {
      var identifier = obj as ExcelCellIdentifier;
      if(identifier == null)
          return false;
      else
          return Equals(identifier);
   }

   public override int GetHashCode()
   {
      //All this below is a common performance thing I add, if you have the two strings "Foo" and "Bar" it will give you a different hash code than the string "Bar" and "Foo", it gives you a better distribution of the hash.
      unchecked
      {
          int hash = 17;
          hash = hash * 23 + Ticker.GetHashCode();
          hash =  hash * 23 + Identifier.GetHashCode();
          return hash;
      }
   }

   public string Ticker { get; set; } //This should likely be changed to {get; private set;}
   public string Identifier { get; set; } //This should likely be changed to {get; private set;}

   public bool Equals(ExcelCellIdentifier other)
   {
      return Ticker.Equals(other.Ticker) && Identifier.Equals(other.Identifier);
   }
}

将这两种方法更改为以下以消除对字符串的区分大小写

   public override int GetHashCode()
   {
      //All this below is a common performance thing I add, if you have the two strings "Foo" and "Bar" it will give you a different hash code than the string "Bar" and "Foo", it gives you a better distribution of the hash.
      unchecked
      {
          int hash = 17;
          hash = hash * 23 + StringComparer.OrdinalIgnoreCase.GetHashCode(Ticker);
          hash =  hash * 23 + StringComparer.OrdinalIgnoreCase.GetHashCode(Identifier);
          return hash;
      }
   }

   public string Ticker { get; set; } //This should likely be changed to {get; private set;}
   public string Identifier { get; set; } //This should likely be changed to {get; private set;}

   public bool Equals(ExcelCellIdentifier other)
   {
      return StringComparer.OrdinalIgnoreCase.Equals(Ticker, other.Ticker) && StringComparer.OrdinalIgnoreCase.Equals(Identifier, other.Identifier);
   }
于 2013-07-16T15:09:55.847 回答
0

正如 Damien_The_Unbeliever 所说,您需要的是:

public class myClass
{
  private readonly Dictionary<ExcelCellIdentifier, int> allInfoByIdentifier =
  new Dictionary<ExcelCellIdentifier, int>(new ExcelCellIdentifier());

  public void testIt()
  {
     allInfoByIdentifier.Add(new ExcelCellIdentifier("Ticker1", "Identifier1"), 4);
     ExcelCellIdentifier ex = new ExcelCellIdentifier("Ticker1", "Identifier1");
     int a = allInfoByIdentifier[ex];
  }
}

   public class ExcelCellIdentifier : IEqualityComparer<ExcelCellIdentifier>
{
  public ExcelCellIdentifier()
  {

  }
    public ExcelCellIdentifier(string ticker, string identifier)
    {
        Ticker = ticker;
        Identifier = identifier;
    }

    public string Ticker { get; set; }

    public string Identifier { get; set; }

    public bool Equals(ExcelCellIdentifier x, ExcelCellIdentifier y)
    {
       return x.Identifier == y.Identifier && 
          x.Ticker == y.Ticker;
    }

    public int GetHashCode(ExcelCellIdentifier obj)
    {
       return obj.Identifier.GetHashCode() ^ 
          obj.Ticker.GetHashCode();
    }

}
于 2013-07-16T14:27:09.210 回答