-
-
Save ilkerde/864508 to your computer and use it in GitHub Desktop.
public IEnumerable<Answer> GetAll() | |
{ | |
List<Answer> answers = GetAnswers(); | |
return answers; | |
} |
Hi,
first of all I wouldn't return IEnumerable here. The materialized vs. lazy question is very important. You have the same discussion in Rx land with "hot" and "cold" observables (http://channel9.msdn.com/Blogs/J.Van.Gogh/Rx-API-in-depth-Hot-and-Cold-observables). IMHO you should reflect this in your signature.
But if you use List or Array you are destroying the whole idea. I would consider a immutable list here.
Immutability is even stronger than the materialized view.
Materialized statement: "I calculated all values for you. Feel free to iterate over the collection as often as you like"
Immutable statement: "I calculated all values for you and they will not change in the future. Feel free to iterate over the collection as often as you like and feel free to store additional information (like checksums)."
That said, there is another interesting point here. Consider the following function:
public IEnumerable<Answer> FilterImportantAnswers(IEnumerable<Answer> allAnswers)
{
return answers.Where(a => a.Important);
}
I often struggle about such functions in .NET, because it is effectively removing type information, like here:
IEnumerable<Answer> answers = FilterImportantAnswers(myImmutableListOfAnswers);
After applying this filter I lose my concrete type and everything is just IEnumerable.
In Haskell one could use type classes to solve this problem. In C# pseudo code something similar could look like this:
public T<Answer> FilterImportantAnswers(T<Answer> allAnswers) where T allows Where
{
return answers.Where(a => a.Important);
}
ImmutableList<Answer> answers = FilterImportantAnswers(myImmutableListOfAnswers);
Regards,
Steffen
Edit:
Sorry. Immutability is not stronger as IEnumerable shows. But they play together.
Materialized statement: "I calculated all values for you. Feel free to iterate over the collection as often as you like"
Immutable and materialized statement: "I calculated all values for you and they will not change in the future. Feel free to iterate over the collection as often as you like and feel free to store additional information (like checksums)."
@steffen: Nice aspect. Unfortunately we can not do
public T FilterImportantAnswers(T allAnswers) where T allows Where
in C#. :-(
That's why I wrote "could" ;-)
@steffen: Sure. I'm sorry that we can't do that in C#. But your answer is a good answer for me "When you should return IEnumerable and when a type with the context of a "materialized" scope." Thx.
@mike: That's not only a problem of C#. It seems this is general problem in .NET generics.
@steffen: Yes, you're totally right.
There is another point. If you return IEnumerable instead of Array or List you are disabling fast indexed access. Why would you do this?
In general: I don't see any value in returning a base class if you could return the concrete class. But maybe I am wrong.
If you want immutability then just use an immutable data structure.
@codefromground thanks for your thoughts. appreciate it. i truly hope that we can dive into topics as this one while having a nice espresso at your site ;) Regarding the ReadonlyCollection: I'm really sorry that my initial example utilized a List. It distracted too much from what i wanted to stress. The second example (using Answer[]) fits more to what i wanted to have opinions for.
@forki Thanks indeed for your in-depth and thoughtful comments.
I do believe that I would have never achieved to express the importance of materialization (and even more, preserving the materialization information by type signature) as you did in your comment.
At this point, I'd like to thank all of you for lending your time and brain for my little question. It was very valuable and insightful.
IMHO the caller should not be bothered by "memorization" aspect. He should not care. IEnumerable could lead the caller to think about "memorization" aspect. List or even IList are a bit to heavy (overhead) for a set of answers IMO. So give Collection and ReadOnlyCollection a thougt. I personally often use IEnumerable for public service interfaces despite it's not recommended by many people. -m2c