C# Corner

The New Read-Only Collections in .NET 4.5

Eric Vogel covers some practical uses for the long awaited interfaces, IReadOnlyList and IReadOnlyDictionary in .NET Framework 4.5.

The Microsoft .NET Framework 4.5 includes the IReadOnlyList, IReadOnlyDictionary and IReadOnlyCollection generic interfaces. The main benefit is that the new interfaces are covariant, except for IReadOnlyDictionary. This means that you can use a derived type as the generic parameter, when passing in a collection into a method that's defined for a base type. If you have a Dog class, for example, that derives from Animal, you can have a method that accepts an IReadOnlyList<Animal> and pass it an IReadOnlyList<Dog>.

The IReadOnlyCollection interface, which forms the base of the IReadOnlyList and IReadOnlyDictionary classes, is defined as IReadOnlyCollection<out T>. The out modifier was added in .NET 4 to denote covariance, whereas the in modifier marks a type as being contravariant. A contravariant type may be substituted by one of its base classes.

Prior to .NET 4.5, the primary covariant collection interface was IEnumerable<out T>. If you wanted to have a read-only view of a List or a Dictionary class, you had to roll your own custom interface, or class, to get the full feature set. Enough theory, let's look at some real applications of these new interfaces.

A common scenario you may run into, is storing a list of people or employees. The application may be a case or customer relationship management system. Either way, you're dealing with similar class representations. For example, if you have a Person class that contains FirstName and LastName properties (Listing 1), and an Employee subclass that adds EIN and Salary properties (Listing 2). This is a very simplified view of a business domain, but it gets the picture across.

You could then create a typed list of Employee objects and access them as a read-only collection using the new interfaces. In a real-world application, your employee list is likely to be quite large and retrieved from a database.

List<Employee> employees = new List<Employee>()
{
    new Employee() { EIN = 1, FirstName = "John", LastName  = "Doe", Salary= 55000M },
    new Employee() { EIN = 2, FirstName = "Jane", LastName = "Doe", Salary= 55000M },
    new Employee() { EIN = 3, FirstName = "Don", LastName  = "DeLuth", Salary= 55000M },
};

The IReadOnlyCollection is the most basic read-only collection interface and provides a Count property on top of its inherent IEnumerable members. For example, you could store a read-only view of employees for a directory listing and easily retrieve the number of people.

IReadOnlyCollection<Person> directory = employees;
int numStaff = directory.Count;

The IReadOnlyList interface is the same as IReadOnlyCollection with the addition of an item indexer.

  IReadOnlyList<Person> staff = employees;
 Person firstHire = staff[0];

The IReadOnlyList would be well-suited for a read-only grid display of the needed items.

The IReadOnlyDictionary interface, as its name suggests, provides a read-only view of the Dictionary class. The accessible Dictionary class members include the Keys, Values and key indexer properties, in addition to the ContainsKey and TryGetValue methods.

Dictionary<int, Employee> einLookUp = employees.ToDictionary(x => x.EIN);
IReadOnlyDictionary<int, Employee> readOnlyStaff = einLookUp;
var eins = readOnlyStaff.Keys;
var allEmployees = readOnlyStaff.Values;
var secondStaff = readOnlyStaff[2];
bool haveThirdEin = readOnlyStaff.ContainsKey(3);
Employee test;
bool fourthExists = readOnlyStaff.TryGetValue(4, out test);

The IReadOnlyDictionary interface could prove useful for validation, as you would not need to modify the items but may want to quickly access them via a key, such as a control identifier.

As you can see, there are many uses for the new read-only collection interfaces. Primarily, they can be used to clean up your application's API to indicate that a method or class should not modify the contents of a collection that it is accessing. One caveat to note is that the interfaces do not provide an immutable copy of the collection but rather a read-only view of the source mutable collection.

About the Author

Eric Vogel is a Senior Software Developer for Red Cedar Solutions Group in Okemos, Michigan. He is the president of the Greater Lansing User Group for .NET. Eric enjoys learning about software architecture and craftsmanship, and is always looking for ways to create more robust and testable applications. Contact him at [email protected].

comments powered by Disqus

Featured

  • Hands On: New VS Code Insiders Build Creates Web Page from Image in Seconds

    New Vision support with GitHub Copilot in the latest Visual Studio Code Insiders build takes a user-supplied mockup image and creates a web page from it in seconds, handling all the HTML and CSS.

  • Naive Bayes Regression Using C#

    Dr. James McCaffrey from Microsoft Research presents a complete end-to-end demonstration of the naive Bayes regression technique, where the goal is to predict a single numeric value. Compared to other machine learning regression techniques, naive Bayes regression is usually less accurate, but is simple, easy to implement and customize, works on both large and small datasets, is highly interpretable, and doesn't require tuning any hyperparameters.

  • VS Code Copilot Previews New GPT-4o AI Code Completion Model

    The 4o upgrade includes additional training on more than 275,000 high-quality public repositories in over 30 popular programming languages, said Microsoft-owned GitHub, which created the original "AI pair programmer" years ago.

  • Microsoft's Rust Embrace Continues with Azure SDK Beta

    "Rust's strong type system and ownership model help prevent common programming errors such as null pointer dereferencing and buffer overflows, leading to more secure and stable code."

  • Xcode IDE from Microsoft Archrival Apple Gets Copilot AI

    Just after expanding the reach of its Copilot AI coding assistant to the open-source Eclipse IDE, Microsoft showcased how it's going even further, providing details about a preview version for the Xcode IDE from archrival Apple.

Subscribe on YouTube

Upcoming Training Events