Search code examples
c#.netsettersortedlist

SortedList<> and its strange setters


I initially had some code, which when simplified, looks like this:

var planets = new List<Planet>
{
    new Planet {Id = 1, Name = "Mercury"},
    new Planet {Id = 2, Name = "Venus"},
};

I got into a scenario where the list was being populated all at once, but the reads weren't fast enough. And so, I changed this to use a SortedList instead.

I later realized that I could rewrite it like this

var planets = new SortedList<int, Planet>
{
    {1, new Planet {Id = 1, Name = "Mercury"}},
    {2, new Planet {Id = 2, Name = "Venus"}},
    //in my actual code, i am reading the ids from a db
};

But before I got to this approach, I had the code written like this

var planets = new SortedList<int, Planet>
{
    Keys = {1, 2},
    Values =
    {
        new Planet {Id = 1, Name = "Mercury"},
        new Planet {Id = 2, Name = "Venus"},
    }
};

which gives me this exception

System.NotSupportedException: This operation is not supported on SortedList
nested types because they require modifying the original SortedList.
  at System.ThrowHelper.ThrowNotSupportedException(ExceptionResource resource)
  at System.Collections.Generic.SortedList`2.KeyList.Add(TKey key)

which I found to be very strange, coz IMHO, I wasn't really modifying the "original SortedList" as it claims, and what "nested types" is it talking about? Is it the list of keys internal to the SortedList?

I see then that the Keys and Values properties in SortedList don't actually have setters. They are read-only properties, and yet, I don't get a compile-time error. I am allowed to make a set call, as I can see in the stack trace with KeyList.Add. I feel the only reason why this fails is because of an explicit check within SortedList, which seems bizarre to me!

For instance var str = new String {Length = 0}; gives me a compile-time error as expected, since Length is a read-only property, as does planets.Keys = null;

Someone please tell me - what simple fact am I overlooking here?


Solution

  • The code that you've written is comparable to this:

    var planets = new SortedList<int, Planet>();
    planets.Keys.Add(1);
    planets.Keys.Add(2);
    planets.Values.Add(new Planet { Id = 1, Name = "Mercury" });
    planets.Values.Add(new Planet { Id = 2, Name = "Venus" });
    

    SortedList requires that you add the value and key at the same time via SortedList<TKey, TValue>.Add(TKey key, TValue value) method, so that it can sort the value by the key. The implementation of the IList<T> which is used for Keys and Values internally does not support adding a respective key or value independently via the IList<T>.Add(T value) method.

    You should be able to reproduce this error by calling Keys.Add(...) or Values.Add(...)