A const list in C# - c#

I would like to create a list in C# that after its creation I won't be able to add or remove items from it. For example, I will create the list;
List<int> lst = a;
(a is an existing list), but after I won't be able to write the code (it will mark it as an error):
lst.Add(2);

.NET supports truly immutable collections, read-only views of mutable collections, and read-only interfaces implemented by mutable collections.
One such immutable collection is ImmutableArray<> which you can create as a.ToImmutableArray() in your example. Make sure to take a look at the other options MSDN lists because you may be better served by a different immutable collection. If you want to make copies of the original sequence with slight modifications, ImmutableList<> might be faster, for instance (the array is cheaper to create and access, though). Note that a.Add(...); is valid, but returns a new collection rather than changing a. If you have resharper, that will warn you if you ignore the return value of a pure method like Add (and there may be a roslyn extension to do something similar I'm unaware of). If you're going this route - consider skipping List<> entirely and going straight to immutable collections.
Read-only views of mutable collections are a little less safe but supported on older versions of .NET. The wrapping type is called ReadOnlyCollection<>, which in your example you might construct as a.AsReadOnly(). This collection does not guarantee immutability; it only guarrantees you can't change it. Some other bit of code that shares a reference to the underlying List<> can still change it. Also, ReadOnlyCollection also imposes some additional overhead; so you may not be winning much by avoiding immutable collections for performance reasons (TODO: benchmark this claim). You can use a read-only wrapper such as this even in a public API safely - there's no (non-reflection) way of getting the underlying list. However, since it's often no faster than immutable collections, and it's also not entirely safe, I recommend to avoid ReadOnlyCollection<> - I never use this anymore, personally.
Read-only interfaces implemented by mutable collections are even further down the scale of safety, but fast. You can simply cast List<> as IReadOnlyList<>, which you might do in your example as IReadOnlyList<int> lst = a. This is my preferences for internal code - you still get static type safety, you're simply not protected from malicious code or code that uses type-checks and casts unwisely (but those are avoidable via code-reviews in my experience). I've never been bitten by this choice, but it is less safe than the above two options. On the upside, it incurs no allocations and is faster. If you commonly do this, you may want to define an extension method to do the upcast for you (casts can be unsafe in C# because they not only do safe upcasts, but possibly failing downcasts, and user-defined conversions - so it's a good idea to avoid explicit casts wherever you can).
Note that in all cases, only the sequence itself is read-only. Underlying objects aren't affected (e.g. an int or string are immutable, but more complicated objects may or may not be).
TL;DR:
For safety: Use a.ToImmutableArray() to create an immutable copy in an ImmutableArray<int>.
For performance: Use IReadOnlyList<int> to help prevent accidental mutation in internal code with minimal performance overhead. Be aware that somebody can cast it back to List<> (don't do that), making this less "safe" for a public api.
Avoid a.AsReadOnly() which creates a ReadOnlyCollection<int> unless you're working on a legacy code base that doesn't support the newer alternatives, or if you really know what you're doing and have special needs (e.g. really do want to mutate the list elsewhere and have a read-only view).

You can use ImmutableList<T> / ImmutableArray<T> from System.Collections.Immutable NuGet:
var immutable = ImmutableList<int>.Create(1, 2, 3);
Or using the ToImmutableList extension method:
var immutable = mutableList.ToImmutableList();
In-case Add is invoked, *a new copy * is returned and doesn't modify the original list. This won't cause a compile time error though.

You need a ReadonlyCollection. You can create one from a list by calling List.AsReadOnly()
Reference: https://msdn.microsoft.com/en-us/library/ms132474.aspx

Why not just use an IEnumerable?
IEnumerable<string> myList = new List<string> { "value1", "value2" };

I recommend using a System.Collections.Immutable.ImmutableList<T> instance but referenced by a variable or property of type System.Collections.Generic.IReadOnlyList<T>. If you just use a naked immutable list, you won't get errors for adding to it, as you desire.
System.Collections.Generic.IReadOnlyList<int> list = a.ToImmutableList();

As an alternative to the already posted answers, you can wrap a readonly regular List<T> into an object that exposes it as IReadOnlyList.
class ROList<T>
{
public ROList(IEnumerable<T> argEnumerable)
{
m_list = new List<T>(argEnumerable);
}
private readonly List<T> m_list;
public IReadOnlyList<T> List { get { return m_list; } }
}
void Main()
{
var list = new List<int> {1, 2, 3};
var rolist = new ROList<int>(list);
foreach(var i in rolist.List)
Console.WriteLine(i);
//rolist.List.Add(4); // Uncomment this and it won't compile: Add() is not allowed
}

Your best bet here is to use an IReadOnlyList<int>.
The advantage of using IReadOnlyList<int> compared to List.AsReadOnly() is that a ReadOnlyCollection<T> can be assigned to an IList<T>, which can then be accessed via a writable indexer.
Example to clarify:
var original = new List<int> { 1, 2, 3 };
IReadOnlyList<int> readOnlyList = original;
Console.WriteLine(readOnlyList[0]); // Compiles.
readOnlyList[0] = 0; // Does not compile.
var readOnlyCollection = original.AsReadOnly();
readOnlyCollection[0] = 1; // Does not compile.
IList<int> collection = readOnlyCollection; // Compiles.
collection[0] = 1; // Compiles, but throws runtime exception.
Using an IReadOnlyList<int> avoids the possibility of accidentally passing the read-only list to a method which accepts an IList<> and which then tries to change an element - which would result in a runtime exception.

It could be IReadOnlyList<int>, e.g.
IReadOnlyList<int> lst = a;
So the initial list (a) is mutable while lst is not. Often we use IReadOnlyList<T> for public properties and IList<T> for private ones, e.g.
public class MyClass {
// class itself can modify m_MyList
private IList<int> m_MyList = new List{1, 2, 3};
...
// ... while code outside can't
public IReadOnlyList<int> MyList {
get {
return m_MyList;
}
}
}

Why not just:
readonly IEnumerable<int> lst = new List<int>() { a }

Related

Difference between returning reference vs not returning anything

Is there a difference between these two methods?
public class A
{
public int Count { get; set; }
}
public A Increment(A instance)
{
instance.Count++;
return instance;
}
public void Increment(A instance)
{
instance.Count++;
}
I mean, apart from one method returning the same reference and the other method not returning anything, both of them accomplish the same thing, to increment the Count property of the reference being passed as argument.
Is there an advantage of using one against the other? I generally tend to use the former because of method chaining, but is there a performance tradeoff?
One of the advantages of the latter method, for example, is that one cannot create a new reference:
public void Increment(A instance)
{
instance.Count++;
instance = new A(); //This new object has local scope, the original reference is not modified
}
This could be considered a defensive approach against new implementations of an interface.
I don't want this to be opinion based, so I am explicitly looking for concrete advantages (or disadvantages), taken out from the documentation or the language's specification.
One of the advantages of the latter method, for example, is that one cannot create a new reference.
You could consider that one of the disadvantages. Consider:
public A Increment(A instance)
{
return new A { Count = instance.Count +1 };
}
Or
public A Increment()
{
return new A { Count = this.Count +1 };
}
Apply this consistently, and you can have your A classes being immutable, with all the advantages that brings.
It also allows for different types that implement the same interface to be returned. This is how Linq works:
Enumerable.Range(0, 1) // RangeIterator
.Where(i => i % 2 == 0) // WhereEnumerableIterator<int>
.Select(i => i.ToString()) // WhereSelectEnumerableIterator<int, string>
.Where(i => i.Length != 1) // WhereEnumerableIterator<string>
.ToList(); // List<string>
While each operation acts on the type IEnumerable<int> each result is implemented by a different type.
Mutating fluent methods, like you suggest, are pretty rare in C#. They are more common in languages without the sort of properties C# supports, as it's then convenient to do:
someObject.setHeight(23).setWidth(143).setDepth(10);
But in C# such setXXX methods are rare, with property setters being more common, and they can't be fluent.
The main exception is StringBuilder because its very nature means that repeatedly calling Append() and/or Insert() on it with different values is very common, and the fluent style lends itself well to that.
Otherwise the fact that mutating fluent methods aren't common means that all you really get by supplying one is the minute extra cost of returning the field. It is minute, but it's not gaining anything when used with the more idiomatic C# style that is going to ignore it.
To have an external method that both mutated and also returned the mutated object would be unusual, and that could lead someone to assume that you didn't mutate the object, since you were returning the result.
E.g upon seeing:
public static IList<T> SortedList(IList<T> list);
Someone using the code might assume that after the call list was left alone, rather than sorted in place, and also that the two would be different and could be mutated separately.
For that reason alone it would be a good idea to either return a new object, or to return void to make the mutating nature more obvious.
We could though have short-cuts when returning a new object:
public static T[] SortedArray<T>(T[] array)
{
if (array.Length == 0) return array;
T[] newArray = new T[array.Length];
Array.Copy(array, newArray, array.Length);
Array.Sort(newArray);
return newArray;
}
Here we take advantage of the fact that since empty arrays are essentially immutable (they have no elements to mutate, and they can't be added to) for most uses returning the same array is the same as returning a new array. (Compare with how string implements ICloneable.Clone() by returning this). As well as reducing the amount of work done, we reduce the number of allocations, and hence the amount of GC pressure. Even here though we need to be careful (someone keying a collection on object identity will be stymied by this), but it can be useful in many cases.
Short answer - it depends.
Long answer - I would consider returning the instance of the object if you are using a builder pattern or where you need chaining of methods.
Most of other cases do look like a code smell: if you are in control of the API and you find a lot of places where your returned object is not used, so why bother with extra effort? possibly you'll create subtle bugs.

Advantage of making a List to a ReadOnlyCollection or AsReadOnly

List<string> dinosaurs = new List<string>();
dinosaurs.Add("Tyrannosaurus");
dinosaurs.Add("Amargasaurus");
dinosaurs.Add("Deinonychus");
dinosaurs.Add("Compsognathus");
Why should I use a ReadOnlyCollection as follows:
var readOnlyDinosaurs = new ReadOnlyCollection<string>(dinosaurs);
instead of:
dinosaurs.AsReadOnly();
What is the real advantage of making a List to a ReadOnlyCollection or a AsReadOnly?
In general, they are the same, as mentioned by Erwin. There is one important case where they differ though. Because the AsReadOnly method is generic, the type of the newly created ReadOnlyCollection is infered, not specifically listed. Normally this just saves you a bit of typing, but in the case of anonymous types it actually matters. If you have a list of anonymous objects you need to use AsReadOnly, rather than new ReadOnlyCollection<ATypeThatHasNoName>.
There is no difference, if you look at the code of AsReadOnly():
public ReadOnlyCollection<T> AsReadOnly()
{
return new ReadOnlyCollection<T>(this);
}
They're equivalent in functionality - but only because you're starting with a List<T>.
The constructor form can be done with any IList<T>, so is the only option in some cases. The other form is a tad more concise, and to some minds (I would agree) a bit nicer in describing just what you are doing.
You should use readonly collection in case when you want to guarantee that none can change that collection. Which is, by the way, doesn't mean that caller will not be able to change the content of that collection.
var collection = List<object> {new SomeObject{...},
new SomeObject{..}}; //SOME OBJECT IS REFERENCE TYPE
var readonly = new ReadOnlyCollection<string>(collection );
readonly[0].SomeObjectProperty = SomeValue; //HERE ORIGINAL OBJECT IS CHANGED
As others said , there is no difference between those 2 calls present in the question.

Convert Dictionary<MyType>.ValueCollection to IList<MyType>

I'm using a Dictionary<int, MyType> in a class. That class implements a interface that requires an IList<MyType> to be returned. Is there a simple way to to cast the one to the other (without copying the entire thing)?
My current solution follows:
private IList<MyType> ConvertToList(Dictionary<int, MyType>.ValueCollection valueCollection)
{
List<MyType> list = new List<MyType>();
list.AddRange(valueCollection);
return list;
}
You'll need to do a copy, but this is probably a good thing. In C# 2, your current code is almost the cleanest you can make. It would be improved by directly constructing your list off your values (List<MyType> list = new List<MyType>(valueCollection);), but a copy will still be required.
Using LINQ with C# 3, however, you would be able to do:
myDictionary.Values.ToList();
That being said, I would not (probably) try to avoid the copy. Returning a copy of your values tends to be safer, since it prevents the caller from causing problems if they attempt to modify your collection. By returning a copy, the caller can do list.Add(...) or list.Remove(...) without causing your class problems.
Edit: Given your comment below, if all you want is an IEnumerable<T> with a Count, you can just return ICollection<T>. This is directly implemented by ValueCollection, which means you can just return your dictionary's values directly, with no copying:
private ICollection<MyType> ConvertToList(Dictionary<int, MyType>.ValueCollection valueCollection)
{
return valueCollection;
}
(Granted, this method becomes really useless in this case - but I wanted to demonstrate it for you...)
How about
Dictionary<int, MyType> dlist = new Dictionary<int, MyType>();
IList<MyType> list = new List<MyType>(dlist.Values);
This is not possible.
A dictionary (including its Values collection) is an inherently unordered collections; its order will change based on the hashcodes of its keys. This is why ValueCollection doesn't implement IList<T> in the first place.
If you really wanted to, you could make a wrapper class that implements IList and wraps the ValueCollection, using a foreach loop in the indexer. However, it's not a good idea.
You can use the constructor:
public IList<MyType> MyValues
{
get { return new List<MyType>(myDictionary.Values); }
}
(Edited to remove an assertion I'm not 100% sure on.)
You can use ToList() method:
myDictionary.Values.ToList();
It is available importing Linq: using System.Linq;

How to expose internal System.Array

I have a class that is a container for two fixed length arrays as well as some other members. I want to expose the elements of the array for assignment outside the class.
Example would be:
using System.Collections.ObjectModel;
class ArrayContainer<T, U>
{
private T[] x;
private U[] y;
// Some other members and constructor
public Collection<T> X
{
get { return new Collection<T>(this.x); }
}
public Collection<U> Y
{
get { return new Collection<U>(this.y); }
}
}
If I try to do instance.X[i] = value I get an exception saying the collection is readonly. So I have three questions:
Why can't I make the above assignment?
Is this the correct was to expose internal members?
Are there any performance issues with making a "new" Collection every time the array is created?
Not sure, but since you are returning a new Collection, it doesn't matter what you do to it. The changes will be lost once the Garbage Collector deletes the Collection. Changes made to the collection will not affect the original array.
No, the correct way would be to either expose the arrays directly, or, if you're worried clients won't play nice, expose them via getters and setters. Since C# only allows 1 property per class with arguments you'll have to use functions for this:
instance.SetX(int index, T value);
T val = instance.GetX(int index);
Yes, making copies always takes extra time and memory. If this is performance critical code, this solution is not acceptable, otherwise, it's probably fine.
Answer to 3:
Your performance is definitely at issue; you'd be creating a new instance each time it was accessed. Any time a person wrote a for... loop you'd get a new instance for each iteration.
Why not publicly just expose your collections? I might do the same thing by simply using List:
class Data<T,U> {
public List<T> X = new List<T>();
public List<U> Y = new List<U>();
}
Writing code would be quite simple:
Data<int, string> theData = new Data<int, string>();
// add
theData.X.Add(37);
theData.Y.Add("foo");
// access
theData.X[0] = 42;
theData.Y[0] = "bar";
// as an array
int[] x = theData.X.ToArray();
If performance really creeps you out, just use arrays instead of List<T>.
If you familiar with concept of interfaces, then you can choose or code the interface explaining what should be external. Then add interface to you class declaration and compiler will help you to do the rest of things properly since.
I have no idea what this is for, but why not use indexers or getter/setter methods? I would think that that would be the typical way of doing this.

Changing the value of an element in a list of structs

I have a list of structs and I want to change one element. For example :
MyList.Add(new MyStruct("john");
MyList.Add(new MyStruct("peter");
Now I want to change one element:
MyList[1].Name = "bob"
However, whenever I try and do this I get the following error:
Cannot modify the return value of
System.Collections.Generic.List.this[int]‘ because it is not
a variable
If I use a list of classes, the problem doesn't occur.
I guess the answer has to do with structs being a value type.
So, if I have a list of structs should I treat them as read-only? If I need to change elements in a list then I should use classes and not structs?
Not quite. Designing a type as class or struct shouldn't be driven by your need to store it in collections :) You should look at the 'semantics' needed
The problem you're seeing is due to value type semantics. Each value type variable/reference is a new instance. When you say
Struct obItem = MyList[1];
what happens is that a new instance of the struct is created and all members are copied one by one. So that you have a clone of MyList[1] i.e. 2 instances.
Now if you modify obItem, it doesn't affect the original.
obItem.Name = "Gishu"; // MyList[1].Name still remains "peter"
Now bear with me for 2 mins here (This takes a while to gulp down.. it did for me :)
If you really need structs to be stored in a collection and modified like you indicated in your question, you'll have to make your struct expose an interface (However this will result in boxing). You can then modify the actual struct via an interface reference, which refers to the boxed object.
The following code snippet illustrates what I just said above
public interface IMyStructModifier
{
String Name { set; }
}
public struct MyStruct : IMyStructModifier ...
List<Object> obList = new List<object>();
obList.Add(new MyStruct("ABC"));
obList.Add(new MyStruct("DEF"));
MyStruct temp = (MyStruct)obList[1];
temp.Name = "Gishu";
foreach (MyStruct s in obList) // => "ABC", "DEF"
{
Console.WriteLine(s.Name);
}
IMyStructModifier temp2 = obList[1] as IMyStructModifier;
temp2.Name = "Now Gishu";
foreach (MyStruct s in obList) // => "ABC", "Now Gishu"
{
Console.WriteLine(s.Name);
}
HTH. Good Question.
Update: #Hath - you had me running to check if I overlooked something that simple. (It would be inconsistent if setter properties dont and methods did - the .Net universe is still balanced :)
Setter method doesn't work
obList2[1] returns a copy whose state would be modified. Original struct in list stays unmodified. So Set-via-Interface seems to be only way to do it.
List<MyStruct> obList2 = new List<MyStruct>();
obList2.Add(new MyStruct("ABC"));
obList2.Add(new MyStruct("DEF"));
obList2[1].SetName("WTH");
foreach (MyStruct s in obList2) // => "ABC", "DEF"
{
Console.WriteLine(s.Name);
}
MyList[1] = new MyStruct("bob");
structs in C# should almost always be designed to be immutable (that is, have no way to change their internal state once they have been created).
In your case, what you want to do is to replace the entire struct in specified array index, not to try to change just a single property or field.
It's not so much that structs are "immutable."
The real underlying issue is that structs are a Value type, not a Reference type. So when you pull out a "reference" to the struct from the list, it is creating a new copy of the entire struct. So any changes you make on it are changing the copy, not the original version in the list.
Like Andrew states, you have to replace the entire struct. As that point though I think you have to ask yourself why you are using a struct in the first place (instead of a class). Make sure you aren't doing it around premature optimization concerns.
In .Net 5.0, you can use CollectionsMarshal.AsSpan() (source, GitHub issue) to get the underlying array of a List<T> as a Span<T>. Note that items should not be added or removed from the List<T> while the Span<T> is in use.
var listOfStructs = new List<MyStruct> { new MyStruct() };
Span<MyStruct> spanOfStructs = CollectionsMarshal.AsSpan(listOfStructs);
spanOfStructs[0].Value = 42;
Assert.Equal(42, spanOfStructs[0].Value);
struct MyStruct { public int Value { get; set; } }
This works because the Span<T> indexer uses a C# 7.0 feature called ref returns. The indexer is declared with a ref T return type, which provides semantics like that of indexing into arrays, returning a reference to the actual storage location.
In comparison the List<T> indexer is not ref returning instead returning a copy of what lives at that location.
Keep in mind that this is still unsafe: if the List<T> reallocates the array, the Span<T> previously returned by CollectionsMarshal.AsSpan won't reflect any further changes to the List<T>. (Which is why the method is hidden in the System.Runtime.InteropServices.CollectionsMarshal class.)
Source
There is nothing wrong with structs that have exposed fields, or that allow mutation via property setters. Structs which mutate themselves in response to methods or property getters, however, are dangerous because the system will allow methods or property getters to be called on temporary struct instances; if the methods or getters make changes to the struct, those changes will end up getting discarded.
Unfortunately, as you note, the collections built into .net are really feeble at exposing value-type objects contained therein. Your best bet is usually to do something like:
MyStruct temp = myList[1];
temp.Name = "Albert";
myList[1] = temp;
Somewhat annoying, and not at all threadsafe. Still an improvement over a List of a class type, where doing the same thing might require:
myList[1].Name = "Albert";
but it might also require:
myList[1] = myList[1].Withname("Albert");
or maybe
myClass temp = (myClass)myList[1].Clone();
temp.Name = "Albert";
myList[1] = temp;
or maybe some other variation. One really wouldn't be able to know unless one examined myClass as well as the other code that put things in the list. It's entirely possible that one might not be able to know whether the first form is safe without examining code in assemblies to which one does not have access. By contrast, if Name is an exposed field of MyStruct, the method I gave for updating it will work, regardless of what else MyStruct contains, or regardless of what other things may have done with myList before the code executes or what they may expect to do with it after.
In addition to the other answers, I thought it could be helpful to explain why the compiler complains.
When you call MyList[1].Name, unlike an array, the MyList[1] actually calls the indexer method behind the scenes.
Any time a method returns an instance of a struct, you're getting a copy of that struct (unless you use ref/out).
So you're getting a copy and setting the Name property on a copy, which is about to be discarded since the copy wasn't stored in a variable anywhere.
This tutorial describes what's going on in more detail (including the generated CIL code).
As of C#9, I am not aware of any way to pull a struct by reference out of a generic container, including List<T>. As Jason Olson's answer said:
The real underlying issue is that structs are a Value type, not a Reference type. So when you pull out a "reference" to the struct from the list, it is creating a new copy of the entire struct. So any changes you make on it are changing the copy, not the original version in the list.
So, this can be pretty inefficient. SuperCat's answer, even though it is correct, compounds that inefficiency by copying the updated struct back into the list.
If you are interested in maximizing the performance of structs, then use an array instead of List<T>. The indexer in an array returns a reference to the struct and does not copy the entire struct out like the List<T> indexer. Also, an array is more efficient than List<T>.
If you need to grow the array over time, then create a generic class that works like List<T>, but uses arrays underneath.
There is an alternative solution. Create a class that incorporates the structure and create public methods to call the methods of that structure for the required functionality. Use a List<T> and specify the class for T. The structure may also be returned via a ref returns method or ref property that returns a reference to the structure.
The advantage of this approach is that it can be used with any generic data structure, like Dictionary<TKey, TValue>. When pulling a struct out of a Dictionary<TKey, TValue>, it also copies the struct to a new instance, just like List<T>. I suspect that this is true for all C# generic containers.
Code example:
public struct Mutable
{
private int _x;
public Mutable(int x)
{
_x = x;
}
public int X => _x; // Property
public void IncrementX() { _x++; }
}
public class MutClass
{
public Mutable Mut;
//
public MutClass()
{
Mut = new Mutable(2);
}
public MutClass(int x)
{
Mut = new Mutable(x);
}
public ref Mutable MutRef => ref Mut; // Property
public ref Mutable GetMutStruct()
{
return ref Mut;
}
}
private static void TestClassList()
{
// This test method shows that a list of a class that holds a struct
// may be used to efficiently obtain the struct by reference.
//
var mcList = new List<MutClass>();
var mClass = new MutClass(1);
mcList.Add(mClass);
ref Mutable mutRef = ref mcList[0].MutRef;
// Increment the x value defined in the struct.
mutRef.IncrementX();
// Now verify that the X values match.
if (mutRef.X != mClass.Mut.X)
Console.Error.WriteLine("TestClassList: Error - the X values do not match.");
else
Console.Error.WriteLine("TestClassList: Success - the X values match!");
}
Output on console window:
TestClassList: Success - the X values match!
For the following line:
ref Mutable mutRef = ref mcList[0].MutRef;
I initially and inadvertently left out the ref after the equal sign. The compiler didn't complain, but it did produce a copy of the struct and the test failed when it ran. After adding the ref, it ran correctly.

Categories