0

I know HashSet can use basic types like string and int, my question is what types are usable in HashSet. I am trying to create a HashSet of Cartesian coords that benefit from HashSet of not having duplicates. I tried

HashSet<int[]> temp = new HashSet<int[]>{new int[]{1,1}, new int[]{1,1} }

but that doesn't work. Looking for a type I can use to create a list of unique coords.

Edward
  • 864
  • 1
  • 7
  • 29
  • 4
    Any type `T`, for which you can define proper `IEqualityComparer` that will implement your meaning of equality, can be usable in `HashSet`. – user4003407 Aug 28 '16 at 17:32
  • So Point doesn't give anything to show it would use IEqualityComparar, on Microsoft website. I looked at Tuple [link](https://msdn.microsoft.com/en-us/library/dd268536(v=vs.110).aspx) would this then be good to use as a HashSet of > ? – Edward Aug 28 '16 at 18:24
  • What you're really asking is why your two arrays don't get treated as the same in a hash set, which is essentially the same question as in the marked duplicate. Another very closely related duplicate is https://stackoverflow.com/questions/7244699/gethashcode-on-byte-array. See also https://stackoverflow.com/questions/7138382/array-comprasion-as-dictionary-keys-in-c-sharp and https://stackoverflow.com/questions/15941389/why-does-my-dictionary-contain-two-entries-with-identical-keys, keeping in mind that dictionaries are basically the same as hash sets, except they pair a value with each key. – Peter Duniho Aug 28 '16 at 19:42
  • @PeterDuniho So I am not as familiar with Dictionary, as such I see that its keys are compared by reference not value, which is basically the same as trying to put an array into the HashSet type of equal value, but no where am I trying to use a getHashCode method/function. I would like to point out the flaw in you marking this as a duplicate; I am asking what types can be used for Hashset that would allow me to use HashSet for coordinate pairs. Which PhilipH explained in his answer about type behavior. – Edward Aug 28 '16 at 19:56
  • _"I see that its keys are compared by reference not value"_ -- only when the same comparison would be used for `HashSet`. Both use `EqualityComparer.Default` unless you provide your own comparer. Reference equality is the default for reference types, but any type can implement other equalities. – Peter Duniho Aug 28 '16 at 21:54
  • _"I am asking what types can be used for Hashset that would allow me to use HashSet for coordinate pairs"_ -- Your question asks _"what types are usable in HashSet."_ and the answer to that is "any type". There are no restrictions; you just have to read the documentation and understand how equality works as the collection uses it. Yes, `Tuple` is _one_ way to approach the problem, but the marked duplicate provides a better, more broadly applicable answer, and most certainly does apply to your question as asked. – Peter Duniho Aug 28 '16 at 21:55
  • I hardly think the post heading equates to the complete question(s) on every post. To your comment on EqualityComparer @PeterDuniho, are you saying then the default of any comparer is the reference type? Then how would you change that to a check on value, without having to write your own method? Also would I just be able to use Point type and add a comparar to it like this? `static void HashSet : IEqualityComparer { }` – Edward Aug 28 '16 at 23:07
  • _"the default of any comparer is the reference type?"_ -- the default comparison for any reference type is reference equality; for value types, it's a field-by-field comparison. A reference type can override the default behavior, and this is in fact what `Tuple` does. You can provide your own comparer as well to these collections, if e.g. you wanted to support arrays directly. _"without having to write your own method?"_ -- if a type doesn't override the equality, you have to write that yourself. – Peter Duniho Aug 28 '16 at 23:14
  • _"would I just be able to use Point type and add a comparar to it like this?"_ -- I don't know what you're asking. There are multiple `Point` types in .NET, the two most commonly used ones are both value types and so already would do the comparison the way you want, just as the `Tuple` class would (but for different reasons, of course). The syntax `static void HashSet : IEqualityComparer { }` that you propose doesn't make sense. I don't know what you're trying to say there. – Peter Duniho Aug 28 '16 at 23:17
  • Well yes someone trying to ask a question who isn't very familiar with the terminology can be a struggle to understand. the syntax i was trying to describe is the same for sub-classes, or when trying to add interfaces, which is what I would be doing if I wanted to implement a comparer is it not? Point (for x,y coords) can be used if I implement the System.Drawing or System.Windows library if I am not mistaken. When I go to Microsoft's page there is not much for that Class, hence why I would think I could possible add a comparer to it by something like static void Point : IEqualityComparer(){} – Edward Aug 28 '16 at 23:23
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/122059/discussion-between-edward-and-peter-duniho). – Edward Aug 28 '16 at 23:51

1 Answers1

3

You are creating a HashSet of reference types. The content of the reference type (unless String) is not compared during equality comparison, only the reference pointer itself.

You are adding two seperate array instances to the HashSet of array instances. Since reference types do not generally compare to each other using their content, only their "memory reference", your code will not work as you intend it to. The two instances are different - even though their content is the same.

The Tuple class overrides this behaviour and compares one instance to another using the sum of the hash codes of its members. Int[] Arrays do not override this behaviour. Most .net Reference Types do not override the comparison operators - Tuple is an exception.

PhillipH
  • 6,182
  • 1
  • 15
  • 25