C# Set Collection

C# Set collection?

Try HashSet:

The HashSet(Of T) class provides high-performance set operations. A set is a collection that contains no duplicate elements, and whose elements are in no particular order...

The capacity of a HashSet(Of T) object is the number of elements that the object can hold. A HashSet(Of T) object's capacity automatically increases as elements are added to the object.

The HashSet(Of T) class is based on the model of mathematical sets and provides high-performance set operations similar to accessing the keys of the Dictionary(Of TKey, TValue) or Hashtable collections. In simple terms, the HashSet(Of T) class can be thought of as a Dictionary(Of TKey, TValue) collection without values.

A HashSet(Of T) collection is not sorted and cannot contain duplicate elements...

What is the C# equivalent of the stl set?


  1. If you require sorted set, use SortedDictionary<T,U>. This is implemented using a binary search tree. Admittedly, you will be using 64-bits per entry because you are storing a key-value pair underneath. You can write a wrapper around it like this:

    class Set<T> : SortedDictionary<T, bool>
    {
    public void Add(T item)
    {
    this.Add(item, true);
    }
    }
  2. If you don't require a sorted set, use HashSet<T>.

  3. Otherwise, check out C5 Generic Collection Library. In particular TreeSet<T>. It is a red-black tree and only stores the values.

Set collection to modified Entity Framework

context.Entry represents a single entity, never a collection. So you have to loop through the collection and mark each entity as modified.

Unique collection set

Expanding on the comments, if you want the row to function as an aggregate hash instead of just as a key, you would want to create a custom IEqualityComparer<(string, string)> and pass it to a HashSet.

public class ValueTupleEqualityComparer : IEqualityComparer<(string s1, string s2)>
{
public bool Equals((string s1, string s2) other)
{
return base.Equals(other);
}

public bool Equals((string s1, string s2) x, (string s1, string s2) y)
{
if (object.ReferenceEquals(x, y))
return true;

if (x.s1 == y.s1 && x.s2 == y.s2)
return true;

if (x.s1 == y.s2 && x.s2 == y.s1)
return true;

return false;
}

public int GetHashCode((string s1, string s2) obj)
{
return base.GetHashCode();
}
}

When testing this against your data set:

var hashSet = new HashSet<(string s1, string s2)>(new ValueTupleEqualityComparer());

hashSet.Add(("txt", "data"));
hashSet.Add(("txt", "txt"));
hashSet.Add(("txt", "data"));
hashSet.Add(("data", "txt"));
hashSet.Add(("exe", "path"));
hashSet.Add(("exe", "path2"));
hashSet.Add(("exe", "path"));

the following results are outputted:

txt data 
txt txt
exe path
exe path2

This gives you unique results where both the "column1" and "column2" are used, regardless of order.

Collection that allows only unique items in .NET?

HashSet<T> is what you're looking for. From MSDN (emphasis added):

The HashSet<T> class provides high-performance set operations. A set is a collection that contains no duplicate elements, and whose elements are in no particular order.

Note that the HashSet<T>.Add(T item) method returns a bool -- true if the item was added to the collection; false if the item was already present.

Does a collection initialize set the initial size of a HashSet properly?

TL;DR; Don't use a collection initializer, if you have a pre-existing array or collection.

The collection initializer just uses Add() to create the collection, so yes, it is slightly better for performance to set the size first. It's unlikely you will actually notice any difference in most cases though.


The code for the relevant HashSet constructor has this little gem:

        public HashSet(IEnumerable<T> collection, IEqualityComparer<T> comparer)
{
...........
// to avoid excess resizes, first set size based on collection's count. Collection
// may contain duplicates, so call TrimExcess if resulting hashset is larger than
// threshold
ICollection<T> coll = collection as ICollection<T>;
int suggestedCapacity = coll == null ? 0 : coll.Count;
Initialize(suggestedCapacity);

this.UnionWith(collection);

So if you have an existing array (which is an ICollection<T>, as is a List<T>) then it won't matter. It's only an issue when using LINQ Where etc, or when using collection initializers.

Modify collection items using reflection?

readonly only applies to the field and means that you cannot assign it another (or the same) collection instance or null. It does not mean that the collection itself is a read-only collection.

Since you have a variable myCollection typed as List<string>, you do not need Reflection. Just write

myCollection.Add("some value"); // allowed.

Note that a List<T> is a class and therefore a reference type. I.e., the variable myCollection contains a reference to the real collection. myCollection.Add("some value"); adds the new value to the real collection (MyAssembly.Constants.MyCollection)!

But something like Constants.MyCollection = null; is not allowed because of the readonly keyword.

Example:

static readonly List<string> myCollection = new List<string>();
static ReadOnlyCollection<string> roc = new ReadOnlyCollection<string>(myCollection);

readonly fields or properties can be initialized with an initializer expression or in a constructor. Given the declarations above:

myCollection.Add("text"); // OK, collection not readonly.
myCollection = new List<string>(); // NOT POSSIBLE, field readonly.

roc.Add("text"); // NOT POSSIBLE, readonly collection has no Add method.
roc = new ReadOnlyCollection<string>(new[] { "a", "b" }); // OK, roc field not readonly.

static does not mean that the field or collection cannot be changed. It means that the field is not an instance field that must be referenced through a class instance (an object), rather, it belongs to the class and can be accessed through the class name.

Example:

class MyClass
{
public static int staticField;
public int instanceField;
}

Given the declaration above:

var obj = new MyClass();
var x = obj.instanceField; // OK
var y = MyClass.staticField; // OK

var z = MyClass.instanceField; // DOES NOT COMPILE!
// CS0120: An object reference is required for the nonstatic field, method, or property
// 'MyClass.instanceField'

var t = obj.staticField; // DOES NOT COMPILE!
// CS0176: Static member 'MyClass.staticField' cannot be accessed with an instance
// reference; qualify it with a type name instead


Related Topics



Leave a reply



Submit