
You want to provide a read-only array or List of elements in your C# program. With the ReadOnlyCollection type in System.Collections.ObjectModel, you can provide a collection of elements that cannot be changed. It may be possible to change some elements themselves, however.
Let's get started with this simple program. A list of integers is created, and then the ReadOnlyCollection constructor is used with that List as an argument. Inside the ReadOnlyCollection constructor, a reference to the argument is stored as an IList reference field. No elements are copied—the constructor is fast.
This C# example program uses the ReadOnlyCollection type from System.Collections.ObjectModel.
Program that uses ReadOnlyCollection [C#]
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
class Program
{
static void Main()
{
List<int> list = new List<int>();
list.Add(1);
list.Add(3);
list.Add(5);
// Constructor.
ReadOnlyCollection<int> read = new ReadOnlyCollection<int>(list);
// Loop over ReadOnlyCollection.
foreach (int value in read)
{
Console.WriteLine("read: {0}", value);
}
// Copy ReadOnlyCollection to an array.
int[] array = new int[3];
read.CopyTo(array, 0);
// Display array.
foreach (int value in array)
{
Console.WriteLine("array: {0}", value);
}
// Use methods on ReadOnlyCollection.
int count = read.Count;
bool contains = read.Contains(-1);
int index = read.IndexOf(3);
Console.WriteLine("{0}, {1}, {2}", count, contains, index);
}
}
Output
read: 1
read: 3
read: 5
array: 1
array: 3
array: 5
3, False, 1
Further notes. You can loop over the ReadOnlyCollection using the standard foreach loop; a for-loop is also possible with the Count property and indexer. The CopyTo method provides a way to copy the elements to an array. You must allocate the array yourself. Finally, the program demonstrates the Count, Contains, and IndexOf methods. These have the same essential functionality as the equivalent methods on the List type.
List Examples List Contains Method List IndexOf Method
Let's get one thing straight with the ReadOnlyCollection. It is the collection itself that is read-only. This means that if you have a ReadOnlyCollection<int>, nothing in the collection can be changed. Ints are value types so changing an int in the collection would change the collection itself.
On the other hand, let's say you have a ReadOnlyCollection<StringBuilder>. This is kind of a strange thing to have, but it is acceptable. You can still change the individual StringBuilder objects by accessing their methods. This is because the StringBuilder references themselves are read-only, but the memory pointed to by the references are still mutable.
Program that changes object in ReadOnlyCollection [C#]
using System;
using System.Collections.ObjectModel;
using System.Text;
class Program
{
static void Main()
{
// Set up the ReadOnlyCollection.
StringBuilder[] array = new StringBuilder[1];
array[0] = new StringBuilder();
var read = new ReadOnlyCollection<StringBuilder>(array);
// Now we change an object pointed to in a ReadOnlyCollection.
read[0].Append("Dot").Append("Net").Append("Perls");
Console.WriteLine(read[0]);
}
}
Output
DotNetPerlsReference note. We can see that read-only status is not transferred to other references. The StringBuilder references are completely normal ones. Please note though that you cannot replace the references with other StringBuilder references or the null literal.

The ReadOnlyCollection in the System.Collections.ObjectModel namespace functions as a wrapper for any collection that implements IList<T>. It does not copy elements; instead it just introduces another level of indirection that impairs the ability to change the collection itself or its values.
Array.AsReadOnly Method Collections