I have a private HashSet<string>
which is the backing field of a read-only property which should return a read-only collection such that callers cannot modify the collection. So I tried to:
public class MyClass
{
private readonly HashSet<string> _referencedColumns;
public ICollection<string> ReferencedColumns {
get { return new ReadOnlyCollection<string>(_referencedColumns); }
}
This does not compile as ReadOnlyCollection
accepts a IList<T>
which is not implememted by HashSet<T>
. Is there another wrapper I can use to save me from copy the items? For my purpose it is enough to just return something implementing ICollection<T>
(instead of IList<T>
) which is implemented by the HashSet<T>
.
How To Make HashSet Read Only In Java? Collections. unmodifiableSet() method is used to create read only HashSet in java. Below program demonstrates that you will not be able to perform modification operations on read only set and modifications to original set are reflected in read only set also.
C# ReadOnlyCollectionUse the ReadOnlyCollection type from System. ReadOnlyCollection makes an array or List read-only. With this type from System. Collections. ObjectModel, we provide a collection of elements that cannot be changed.
The fact that ReadOnlyCollection is immutable means that the collection cannot be modified, i.e. no objects can be added or removed from the collection.
Consider exposing the property as the type IReadOnlyCollection<>
instead, which will provide a read-only view of the HashSet<>
. This is an efficient way of implementing this, since the property getter will not require a copy of the underlying collection.
This will not prevent someone from casting the property to a HashSet<>
and modifying it. If you are concerned with that, consider return _referencedColumns.ToList()
in the property getter, which will create a copy of your underlying set.
You can use the following decorator to wrap the hash set and return an ICollection<T>
that is read-only (the IsReadOnly
property returns true and modification methods throw a NotSupportedException
as specified in the contract of ICollection<T>
):
public class MyReadOnlyCollection<T> : ICollection<T>
{
private readonly ICollection<T> decoratedCollection;
public MyReadOnlyCollection(ICollection<T> decorated_collection)
{
decoratedCollection = decorated_collection;
}
public IEnumerator<T> GetEnumerator()
{
return decoratedCollection.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable) decoratedCollection).GetEnumerator();
}
public void Add(T item)
{
throw new NotSupportedException();
}
public void Clear()
{
throw new NotSupportedException();
}
public bool Contains(T item)
{
return decoratedCollection.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
decoratedCollection.CopyTo(array, arrayIndex);
}
public bool Remove(T item)
{
throw new NotSupportedException();
}
public int Count
{
get { return decoratedCollection.Count; }
}
public bool IsReadOnly
{
get { return true; }
}
}
And you can use it like this:
public class MyClass
{
private readonly HashSet<string> _referencedColumns;
public ICollection<string> ReferencedColumns {
get { return new MyReadOnlyCollection<string>(_referencedColumns); }
}
//...
Please note that this solution will not take a snapshot of the HashSet, instead it will hold a reference to the HashSet. This means that the returned collection will contain a live version of the HashSet, i.e., if the HashSet is changed, the consumer that obtained the read only collection before the change would be able to see the change.
While it is not readonly, Microsoft released a nuget package called System.Collections.Immutable
that contains an ImmutableHashSet<T>
which implements IImmutableSet<T>
which extendsIReadOnlyCollection<T>
Quick usage sample :
public class TrackedPropertiesBuilder : ITrackedPropertiesBuilder
{
private ImmutableHashSet<string>.Builder trackedPropertiesBuilder;
public TrackedPropertiesBuilder()
{
this.trackedPropertiesBuilder = ImmutableHashSet.CreateBuilder<string>();
}
public ITrackedPropertiesBuilder Add(string propertyName)
{
this.trackedPropertiesBuilder.Add(propertyName);
return this;
}
public IImmutableSet<string> Build()
=> this.trackedPropertiesBuilder.ToImmutable();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With