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 |