Multiple indexes over an in memory collection for faster search
Using ToString() to compare expressions for equality might work in simple cases, but:


It requires you to always use the same parameter name, for example, it would consider x =&gt; x.Id and product =&gt; product.Id to be different expressions.
Expressions with different meaning can produce the same string, for example (int i) =&gt; (float)i and (int i) =&gt; (double)i both produce i =&gt; Convert(i). Because of this, it might make sense to ensure that the used expressions contain only property accesses and nothing else.


Instead you should compare Expressions properly.



It seems wasteful to me to rebuild all indexes after each change. If you change the collection often, consider changing only the relevant part of each index.



Fields that are set in the constructor and then never modified should be readonly.



IList&lt;T&gt; data


If you're on .Net 4.5, you could use IReadOnlyList&lt;T&gt; here.



if (_lookups.Count &gt; 0)


This check is pretty much useless. It saves you from unnecessarily creating an empty dictionary, but doing that is very cheap, so I think shorter code should take the priority here.



You could replace the whole RebuildIndexes() method with a single ToDictionary():

_indexes = _lookups.ToDictionary(
    lookup =&gt; lookup.ToString(), lookup =&gt; _items.ToLookup(lookup.Compile()));




c(x).Equals(value)


This won't work correctly when c(x) returns null. You should probably use object.Equals(c(x), value) instead.