I've been reading Eric Lippert's series on immutable collections (start here with part one) over on his blog, Fabulous Adventures in Coding. I don't understand everything he writes, but it's still a fascinating read.

This morning on my commute I was wondering whether it would be possible to "fake" immutability in an existing list class by adding a "With" and "Without" method. The idea would be to ask for a new list which is the same as the original list but "with" a particular item, or to ask for a new list the same as the original "without" one of its items.

Here's some code to illustrate what I mean:

List<int> nums = new List<int>() { 1, 2, 3, 4, 5 };
foreach (int i in nums.With(6))
{ 
    Console.WriteLine(i);
}

foreach (int i in nums.Without(3))
{ 
    Console.WriteLine(i); 
}

 

The idea is that the two "foreach" loops are acting on a completely separate object to the original "nums" list. Calling "With" and "Without" constructs a new list rather than modifying the original.

As it turns out this sort of thing is pretty easy to do with extension methods, and I even found a way to make them work on any class that implements IList<T>. Here's my code:

public static class ListExtensions 
{ 
    public static TList With<TList, T>(this TList list, T item) 
        where TList : IList<T>, new() 
    { 
        TList l = new TList();
        foreach (T i in list) 
        { 
            l.Add(i); 
        } 
        l.Add(item); 
        return l; 
    } 

    public static TList Without<TList, T>(this TList list, T item) 
        where TList : IList<T>, new() 
    { 
        TList l = new TList(); 
        foreach (T i in list.Where(n => !n.Equals(item))) 
        { 
            l.Add(i); 
        } 
        return l; 
     } 
}

This is probably not the most efficient way to do it, and I'm not suggesting for a second that someone would start bandying the term "immutable" about when referring to a plain old IList<T>, but I still thought it was an interesting thought experiment into what's possible with extension methods.