Recently, we were editing some code for a client, specifically code that creates a list of an anonymous class, and then runs a LINQ statement on it.
As part of the edit, we had to set the values of this class differently under different conditions. Regardless of the situation, though, the structure would end up the same. We ended up with something similar to this:
If (boolCondition) var items = itemSourceOne.Select(x => new {id = x.id, value = x.value}).ToList(); else var items = itemSourceOther.Select(x => new {id = x.id, value = x.value}).ToList(); finalList = items.Where(x => x.value != 0).ToList();
But the code didn’t run. The LINQ statement requires a specific reference to one of the class’s properties. Even if the anonymous class is defined having the same structure in every possible path of the if block, none of the properties can be referenced outside the block. The list’s structure had to be defined outside the if block in order for this code to work, but the content can’t be assigned outside the block. In short, we needed to define an empty list of an anonymous class.
Unfortunately, after much research, we found that is no real good way to create such a definition. The only ways we could find to do this are cheap, messy hacks, such as adding a creating the list with a dummy item and then removing it, or initializing the list to enumerable.repeat with a length of 0. Alternatively, we could have moved the LINQ statement at the end into both the if and else blocks, but duplicating code is also bad design.
We found that the best way to get around this is to define it as a named class type, so it’s no longer anonymous. However, even though it’s a lot cleaner than the other things we found, we didn’t really like this idea either. Defining a whole class for a simple two field class that is only used in this one method, where it is promptly converted to JSON before being returned, just doesn’t seem very efficient or clean either.
Fortunately, in our case, we (thankfully) got a reprieve when we deduced that, due to the client’s business logic, the list will only contain an entry that would be affected by the LINQ statement if the condition is true. Thus, we were able to solve the problem by putting the LINQ statement inside the if block. However, it seems we’ve found a limitation of anonymous classes. What would we have done if the LINQ statement always has a chance of affecting the list?