There are 3 ways of adding items to most lists…
- via a direct public API method, typically
Add(SomeType) - via the generic
IList<T>.Add(T)interface - via the non-generic
IList.Add(object)interface method
and you normally expect them to behave more or less the same. However, LINQ’s EntitySet<T> is… peculiar on both 3.5 and 4.0; the IList API does not flag the set as “assigned” – the other two mechanisms do – this sounds trivial, but it is important in that it heavily influences serialization (i.e. causes it to be skipped) in the boilerplate code.
Example:
EntitySet<string> set1 = new EntitySet<string>();
set1.Add("abc");
Debug.Assert(set1.Count == 1); // pass
Debug.Assert(set1.HasLoadedOrAssignedValues, "direct"); // pass
EntitySet<string> set2 = new EntitySet<string>();
IList<string> typedList = set2;
typedList.Add("abc");
Debug.Assert(set2.Count == 1); // pass
Debug.Assert(set2.HasLoadedOrAssignedValues, "typed list"); // pass
EntitySet<string> set3 = new EntitySet<string>();
IList untypedList = set3;
untypedList.Add("abc");
Debug.Assert(set3.Count == 1); // pass
Debug.Assert(set3.HasLoadedOrAssignedValues, "untyped list"); // FAIL
Now… this is deeply surprising to me; so much so that it took me over 2 hours of tracking upwards through code to isolate what was happening. So…
is there any sane reason for this? Or is this just a bug?
(FWIW, there was also an issue in set.Assign(set) in 3.5, but this is now fixed in 4.0.)
Interestingly, this has been identified for several versions now (you stated that a 3.5 issue was fixed in 4.0). Here is a post from 2007. The rest of the
IListmethods in 4.0 are correctly tied to theIList<T>methods. I think that there are 2 likely explanations (of the bug/feature variety):exploitingleveraging to add items without setting theHasLoadedOrAssignedValues.It is probably both – a bug that other code inside the framework is counting on. Sounds like someone said to themselves: