3

Right now I have a const array of strings and loop through to check if a value exists. But I want a more efficient way to store my values. I know there's a hashset which I can use like so:

HashSet<string> tblNames = new HashSet<string> ();
tblNames.Add("a");
tblNames.Add("b");
tblNames.Add("c");

However, is it possible to make this a constant member of my class like this:

public const HashSet<string> tblNames = new HashSet<string>() { "value1", "value2" };
4
  • 3
    But I want a more efficient way to store my values. What do you mean by more efficient?
    – mjwills
    Commented Apr 3, 2019 at 1:37
  • 4
    I'd suggest using static readonly rather than const. Alas, since it is public other code will be able to add or remove items from the HashSet.
    – mjwills
    Commented Apr 3, 2019 at 1:40
  • 2
    To be fair, I don't think this is necessarily a duplicate of the const questions, as they don't address preventing the Set contents from being added/removed.
    – NPras
    Commented Apr 3, 2019 at 5:06
  • 1
    The OP probably wants an immutable HashSet<T>. There is an ImmutableHashSet<T> class in the package System.Collections.Immutable. Commented Sep 15, 2019 at 5:09

1 Answer 1

14

The best way to create a 'constant' Set is probably by exposing your HashSet as its IEnumerable interface, using the following:

public static readonly IEnumerable<string> fruits = new HashSet<string> { "Apples", "Oranges" };
  • public: everyone can access it.
  • static: there's only going to be one copy in memory, no matter how many instances of the parent class is created.
  • readonly: you can't re-assign it to a new value.
  • IEnumerable<>: you can only iterate through its contents, but not add/remove/modify.

To search, you can use LINQ to call Contains() on your IEnumerable, and it is smart enough to know it's backed by a HashSet and delegate the proper call to utilise the hashed nature of your set. (well, ok, it calls it via ICollection, but ends up in HashSet's overridden method anyway)

Debug.WriteLine(fruits.Contains("Apples")); // True
Debug.WriteLine(fruits.Contains("Berries")); // False

fruits = new HashSet<string>(); // FAIL! readonly fields can't be re-assigned
fruits.Add("Grapes"); // FAIL! IEnumerables don't have Add()
4
  • I am curious why a const field can't be marked as static but a readonly value can
    – DannyD
    Commented Apr 3, 2019 at 18:38
  • 1
    From the C# language spec: A constant or type declaration is implicitly a static member
    – NPras
    Commented Apr 4, 2019 at 0:47
  • This is not constant it's readonly. Therefore useless when the expression must be constant. Would be more useful to investigate whether or not it is possible to create a constant hash table in C#. Commented Jun 30, 2022 at 19:16
  • 1
    Just to clarify on this and it is smart enough to know it's backed by a HashSet and delegate the proper call to utilise the hashed nature of your set. (well, ok, it calls it via ICollection, but ends up in HashSet's overridden method anyway) IEnumerable and ICollection are simply interfaces. They do not define default implementations for Contains(). When you call Contains() it will directly call the hashset implementation.
    – JFord
    Commented Jul 29, 2022 at 21:24

Not the answer you're looking for? Browse other questions tagged or ask your own question.