Question

What is the most efficient way to cast a Dictionary<int, List<User>> to a Dictionary<int, IEnumerable<User>>?

The reason for this is that I have a method which builds a Dictionary<int, List<User>> but I would prefer not to return a mutable List to the calling code.

Would I have to project this dictionary into the new type?

Was it helpful?

Solution 2

You can return an IEnumerable but under the hood it'll be a List. A developer may well cast it to a List and add or remove items

I think you're looking for Immutable Collections

Briefly, it's a nuget package that enable us to use/create truly immutable collections; meaning that any collections changes are not reflected back to what exposed them.

EDIT: Cast to IEnumerable does not grant immutability

Given Guilherme Oliveira answer one can do the following and add a new user to the users

    var userDictionary = new Dictionary<int, List<User>>();
    userDictionary.Add(1, new List<User>
    {
        new User{ Name= "Joseph"},
    });
    IDictionary<int, IEnumerable<User>> newDictionary = userDictionary.ToDictionary(p => p.Key, p => p.Value.AsEnumerable());
    ((List<User>) newDictionary.Values.First()).Add(new User {Name = "Maria"});
    Console.WriteLine(newDictionary.Values.First().Count()); //now we have two users

OTHER TIPS

You can do just like this:

var userDictionary = new Dictionary<int, List<User>>();
IDictionary<int, IEnumerable<User>> newDictionary = userDictionary.ToDictionary(p => p.Key, p => p.Value.AsEnumerable());

You would need to project this to a new dictionary, e.g.

Dictionary<int, List<User>> myDictionary = ...;
Dictionary<int, IEnumerable<User>> resultingDictionary = myDictionary.ToDictionary(kvp => kvp.Key, kvp => (IEnumerable<User>)kvp.Value)

You are unable to perform a cast from Dictionary<int, List<User>> to Dictionary<int, IEnumerable<User>> because if you could, the following would be possible:

Dictionary<int, List<User>> myDictionary = ...;
// Still a reference to the original dictionary
Dictionary<int, IEnumerable<User>> castDictionary = myDictionary;

// If the line above was possible, what would this do? (A HashSet<T> is not a List<T>)
castDictionary.Add(5, new HashSet<User>());

You may also want to take a look at covariance and contravariance on interfaces to see where the limitations lie.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top