5

I'm thinking specifically about the generic class HashSet<T>. It implements several interfaces, but none exposes the correct semantics of a set. Specifically, none supports an Add method returning bool. (ICollection<T> supports void Add, which can be used in a pinch.) Also unsupported by these interfaces are common set operations like unions and intersections. (Though it must be said that some of these operations are available via extensions to IEnumerable<T>.)

This means the class can only be used like a set with its direct implementation. I.e., you can't do something like this:

ISet<int> = new HashSet<int>;

Not as far as I know, anyway. So what motivated the choice to leave this out?

Maybe the most important thing is this: even if you can cast HashSet<T> to ICollection<T> et al, you lose semantic value in the API you're exposing. That is, consumers of your API have no indication they're working with a set. So while you could call ICollection<T>.Add and get by, people will be confused if they try to add an item twice and it doesn't work. A set interface would give people the right expectations.

Sean Devlin
  • 1,662
  • 12
  • 17
  • What would `ISet` have that `ICollection` doesn't have? – Dan Tao Feb 04 '10 at 12:48
  • Oh I think I see... an `Add` method that returns a `bool`, eh? – Dan Tao Feb 04 '10 at 12:50
  • @dan - you can't add duplicates to a set. – UpTheCreek Feb 04 '10 at 12:50
  • @dan - `IsSubsetOf`, `UnionWith`, etc. – Jørn Schou-Rode Feb 04 '10 at 12:58
  • @Sosh, that's not what dan is asking. What's to stop you implementing a collection with Set semantics behind the ICollection interface? i.e. ICollection = new HashSet(); As Dan says, the missing part of the API is the bool return from the Add method, along with those few other methods which are included in the ISet interface in .NET 4.0. – Iain Galloway Feb 04 '10 at 13:01
  • 1
    What do you mean only be used with it's direct implementation? declare you variable/parameter of ICollection and you have access to the add method. That contract however doesn't really say that it's a set but that's not because of the explicit implementation – Rune FS Feb 04 '10 at 13:10
  • @Rune FS I guess you're right about that. I'll edit the question. – Sean Devlin Feb 04 '10 at 13:17
  • @Sosh: I'm aware of that; I was just thinking, you can call `Add` on a set just like a collection--doesn't mean it has to succeed. But obviously, returning a bool to indicate success is a different interface. – Dan Tao Feb 04 '10 at 13:29
  • Right, sorry for the missunderstanding. – UpTheCreek Feb 05 '10 at 07:25

2 Answers2

8

While I am not sure why it hasn't made it into the base class library earlier, an ISet is available in .NET 4.0, which is only weeks from shipping. The interface has most of the methods you would expect on a set. These are some of the supported methods:

  • Add, Clear, Contains, CopyTo, GetEnumerator, Remove (inherited)
  • ExceptWith
  • IntersectWith
  • IsSubsetOf
  • IsSupersetOf
  • Overlaps
  • UnionWith

The HashSet and SortedSet collections implement this new interface.

Jørn Schou-Rode
  • 37,718
  • 15
  • 88
  • 122
  • 1
    It actually didn't even occur to me to check if it would be in .NET 4.0. I figured that if it hadn't been included by now, there must be some reason for it. :) I'll be looking forward to this for future projects. – Sean Devlin Feb 04 '10 at 13:28
0

Check out Iesi.Collections.ISet which adds this functionality missing from the standard library.

UpTheCreek
  • 31,444
  • 34
  • 152
  • 221