Once again about IEnumerable
IEnumerable is such a nature that it is essentially a action and not an object. The only way to be sure of this is to look at what it is transformed by msbuild.
It’s like the difference between the subject and the predicate from point of view of grammar and philology - the object and the action. Both are parts of speech. Elements (aka object) from the point of view of philology and syntax, having their own properties and features.
Psychologically, to think about IEnumerable as action helps to perceive reality more easily.
string[] is a reference to an object. It already has a value.
IEnumerable is a reference to an Enumerator (object of course), but being an action, before getting a value it must be executed.
Here the everything are static.
1
2
3
int [] a;
int [] b;
int[] c = [..a, ..b];
Here, everything is possible, including any side effect, just like when performing any function.
1
2
3
IEnumarable<string> a;
IEnumarable<string> b;
var c = [..a, ..b];
Examples
- https://github.com/dotnet/docs/blob/main/docs/csharp/language-reference/statements/snippets/yield/Program.cs
https://github.com/dotnet/docs/blob/main/docs/csharp/snippets/iterators/Generators.cs
How it is commonly used.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
class Snippet { internal IEnumerable<int> @Yield() { yield return 1; yield return 2; } public IEnumerable<int> DoWhile() { int index = 0; while (index < 10) yield return index++; } internal IEnumerable<int> @Array => new[] { 1, 2, }; internal IEnumerable<int> @For() { foreach (int i in Enumerable.Range(0,2)) { Console.WriteLine(i); yield return i; } } internal IEnumerable<int> SeveralFor() { foreach (int i in Enumerable.Range(0, 2)) yield return i; foreach (int i in Enumerable.Range(2, 2)) yield return i; } internal void Enumerate() { List<int> collection= [4,5]; IEnumerator<int> enumerator = collection.GetEnumerator(); while (enumerator.MoveNext()) { Console.WriteLine( enumerator.Current.ToString()); } } internal IEnumerable<int[]> WithSideEffect(int i) { // These messages will only be in the first loop! Console.WriteLine(i); if (i>0) Console.WriteLine(i); Console.WriteLine("first loop"); yield return [1, 2]; Console.WriteLine("second loop"); yield return [3, 4]; } internal IEnumerable<int> Wrapper { get { int CreateParameters(int i) { Console.WriteLine(i); return i; } yield return CreateParameters( 1); yield return CreateParameters( 2); } } // xunit MemberData internal IEnumerable<object[]> MemberData { get { object[] CreateParameters(Action<int> call, int expected) { return new object[] { call, expected }; } yield return CreateParameters(Console.WriteLine, 1); yield return CreateParameters(Console.WriteLine, 2); } } }