Skip to main content

Timeline for C#'s Aversion to Array

Current License: CC BY-SA 4.0

16 events
when toggle format what by license comment
Jun 25 at 21:14 comment added Basilevs @K0D4 remember, interfaces are designed to be usable forever, not just today. You do not make decisions based on today's implementation, you make them to support tomorrow's clients for unknown implementation.
Jun 25 at 21:08 comment added Basilevs @K0D4 Immutable Length is bad because it prevents service from poulating data lazily in the future. The way data is obtianed is implementation detail, interface should not dictate whether the data is eagerly fetched. On that not Count is amost as bad, because it is not synchronized with iteration.
Jun 25 at 21:01 comment added K0D4 In the case of data access patterns, IEnumerable would only provide "Count" which is up to an implementation detail to decide. Maybe a list keeps a "count" around privately, but the same isn't necessarily true about every underlying implementation of IEnumerable. Array has a .Length, which is a property and the accessor for it is immediate. There's no enumeration or "counting" needed to determine its length. An array is complete, and known, and I don't see that as being bad or a limitation, or even leaking anything bad to a caller. Maybe in C++ with unbounded array checks, but this is C#.
Jun 24 at 18:36 comment added Bobson @coredump It's the difference between how the interface is defined and exposed vs what the code does internally. If the function is declared to return a List<int> but you use something derived from that internally, that's valid. But what's visible is going to be List<int>. What this answer and comments are saying is that that's still too specific and it should be defined to return IList<int> or IEnumerable<int>. But internal to the code it can still return a List<int> or something derived from it.
Jun 23 at 16:16 comment added coredump Maybe this is different in C#, but if I return a more precise type when implementing an interface, users that manipulate the data through the interface only see the general type. The internal layer sees the actual type. That's probably the thing I did not communicate well here. This is like having two methods, the internal one that returns an array and the public one that wraps it and returns the IEnumerable.
Jun 23 at 14:48 comment added Basilevs @coredump when API has a general type, compiler protects clients from relying on specific type. When API provides a specific type, clients are not protected and may use however they want. This effectively means, they WILL use the specific type and WILL break when the API is changed.
Jun 23 at 11:43 comment added coredump This is in conjunction with other methods accepting the most general types, like IEnumerable. These methods do not rely on the fact that it is an array. But private methods can access the actual type if needed.
Jun 23 at 11:32 comment added Basilevs @coredump this approach produces a brittle API. Do not expose any information unless there is a specific need for it.
Jun 23 at 11:28 comment added coredump In general I'm on the side of returning the most precise type (stackoverflow.com/a/3434385/124319)
Jun 23 at 11:06 comment added Basilevs @Heinzi Materializing a large collection is something I often have to avoid. In Java this is done with Stream which does not support multiple traversals. The argument about traversals does not hold for C# though, given the Reset method.
Jun 23 at 8:16 comment added Heinzi I agree that array or List is (usually) too strong a contract. In my personal experience, though, IEnumerable is often too weak: It does not even guarantee that the collection is materialized, which is something (a) that I am often willing to guarantee and (b) that avoids extra defensive .ToList() calls at the consumer that would be needed if the collection were to be enumerated more than once. Hence, ICollection<T> has become my go-to type for returning collections in business software, as a compromise between the two extremes.
Jun 21 at 13:57 history edited Basilevs CC BY-SA 4.0
edited body
Jun 21 at 10:36 history edited Basilevs CC BY-SA 4.0
edited body
Jun 21 at 0:48 comment added Greg Burghardt I think this answer most directly addresses the heart of the question, especially the first sentence. Spot on.
Jun 20 at 21:50 history edited Basilevs CC BY-SA 4.0
added 57 characters in body
Jun 20 at 21:45 history answered Basilevs CC BY-SA 4.0