29

I am wondering if there is any set-like readonly interface that declares a Contains method in C#. I don't want to just implement the ISet interface because it has too many unnecessary methods.

My idea implementation would be like thi:

public class PositiveInt : IReadOnlySet<Int32>
{
   public bool Contains(Int32 n){
      return n > 0;
   }
}

public class CraEmployeeNames:IReadOnlySet<String>
{
   public bool Contains(String n){
      return !String.IsNullOrWhiteSpace(n) && n.StartsWith("Cra");
   }
} 

I can define my own IReadOnlySet, but want to ensure there is no built-in one before I do.

Jeroen
  • 60,696
  • 40
  • 206
  • 339
Wei Ma
  • 3,125
  • 6
  • 44
  • 72
  • 3
    Do you mean [ReadOnlyCollection](http://msdn.microsoft.com/en-us/library/ms132474(v=vs.110).aspx) or the [readonly](http://msdn.microsoft.com/en-us/library/acdd6hb7.aspx) keyword – Liam May 14 '14 at 15:26
  • It seems to me your are trying to validate your data. Why are you using this approach to validate your data values? – Flater May 14 '14 at 15:26
  • 2
    The readonly keyword is kind of useless here isn't it? – Charleh May 14 '14 at 15:28
  • 1
    If you only want a `Contains` method you could just use a `Func`. – Lee May 14 '14 at 15:28
  • Maybe, depends, this all sounds a lot like an [XY Problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) – Liam May 14 '14 at 15:29
  • 1
    Agreed, but suggesting readonly keyword when you don't know what the X is...? – Charleh May 14 '14 at 15:34
  • 3
    Sadly, they didn't make an `IReadOnlySet`, and if they did, it would likely have the vast majority of the methods you're complaining about having to implement. So create an `IContainsCollection : ICollection { Contains(T); }`, or implement `ISet` partially with `NotImplementedException`s on the rest, or create `IContains { Contains(T); }`, etc. etc. What are you trying to do? If you answer that, we can suggest something intelligently – Tim S. May 14 '14 at 15:39
  • Thanks @Tim, I would like to implement some kind of tester to test if an element is in a pre-defined---eh---set. So my sample implementation actually explains my intention quite clearly. I want to "declare" characteristics of a Set, but not by add into it. – Wei Ma May 14 '14 at 15:43
  • @WeiMa Then it sounds like my `IContains` is all you need. – Tim S. May 14 '14 at 16:12
  • 1
    Your `IReadOnlySet`, if you make one, should also probably inherit from `IEnumerable`. In addition to calling `Contains` on a read only set, one may want to iterate it. – Servy May 14 '14 at 16:34
  • 1
    But the mathematics definition of Set has no where mentioning that it should be "Enumerable", so I do see why I should inherit from IEnumerable. – Wei Ma May 14 '14 at 17:05
  • 1
    It's true that a mathematical set might not be enumerable (e.g. the set of all real numbers), but `ISet` is. If you use the name `IReadOnlySet` in C#, I'd expect it to be similar to `ISet` but read-only, which means `IEnumerable` is implemented, `Count` exists, etc. Your examples do not appear to match this rule. (which is why I named it `IContains` in my solution) – Tim S. May 14 '14 at 18:28
  • That is why probably IContains make more sense:) I already implemented it. – Wei Ma May 14 '14 at 18:33
  • https://github.com/dotnet/roslyn/blob/master/src/Compilers/Core/Portable/InternalUtilities/IReadOnlySet.cs – Mauricio Scheffer May 04 '15 at 23:39
  • 1
    This wouldn’t be such a big deal if `IReadOnlyCollection(T)` provided `Contains()` like `ICollection(T)` does. No idea why that’s missing. – binki Dec 01 '15 at 20:08

4 Answers4

9

How about the IImmutableSet<T> interface?

Stephen Kennedy
  • 20,585
  • 22
  • 95
  • 108
xtofs
  • 421
  • 6
  • 8
8

Edit 17 September 2020: .NET 5.0 now offers the new interface IReadOnlySet<T>:


No, there is no IReadOnlySet<T> interface in C#. Based on the needs you've described, I think you should create your own IContains<T> interface.

public interface IContains<T>
{
    bool Contains(T item);
}

Note that this can not be added to existing collections like List<T> or HashSet<T>, and doesn't contain any other set-like operations like Count or enumeration. You might use it like:

public void TestContains<T>(IContains<T> container, T item)
{
    if (container.Contains(item))
    {
        //something
    }
    else
    {
        //something else
    }
}
Patrick from NDepend team
  • 13,237
  • 6
  • 61
  • 92
Tim S.
  • 55,448
  • 7
  • 96
  • 122
2

It is in the Microsoft.SqlServer.Management.Sdk namespace. See:

https://msdn.microsoft.com/en-us/library/microsoft.sqlserver.management.sdk.sfc.ireadonlyset.aspx

I don't know why it is there, instead of with the rest of the IReadOnlyYadaYada<> interfaces in .NET itself. Probably some snafu. And probably, fear of collision is the reason they have not put it into .NET itself. Which is a shame.

Also, see this question: Why does List implement IReadOnlyList in .NET 4.5?

Community
  • 1
  • 1
Kafka
  • 101
  • 2
1

In .Net 5 and above, IReadonlySet<T> is added. In this version of .Net, Microsoft has started to support Immutality. There are several classes and interfaces in System.Collections.Generic Namespace to support immutable functionality. For instance you can use ImmutableList<T> which is one my favorites.

By the following code snippet, you can convert IEnumerable<T> to IReadOnlySet<T>:

public static IReadOnlySet<T> ToReadOnlySet<T>([DisallowNull] this IEnumerable<T> items) => ImmutableList.CreateRange(items).ToHashSet();
Mohammad Mirmostafa
  • 1,720
  • 2
  • 16
  • 32