Skip to content

Commit 174bb2e

Browse files
IEnumerable in C#: retarget net10.0, Book record, GenericLibrary with yield return, LibraryTests (#2297)
Both projects net7.0 to net10.0. Microsoft.NET.Test.Sdk 18.11.0, xunit 2.9.3, xunit.runner.visualstudio 4.0.1, coverlet.collector 10.1.0. Book becomes a positional record, the Library constructor copies with a collection expression, Program.cs moves to top-level statements and gains the GenericLibrary query, file-scoped namespaces. New GenericLibrary implements IEnumerable<Book> with yield return. The test project references the console project and gains LibraryTests (iteration order from the -1 start, Cast before LINQ on the non-generic Library, LINQ directly on GenericLibrary, Reset on the generated enumerator throws NotSupportedException).
1 parent 80ff2dd commit 174bb2e

8 files changed

Lines changed: 142 additions & 81 deletions

File tree

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,3 @@
1-
namespace IEnumerableCSharp
2-
{
3-
public class Book
4-
{
5-
public Book(string name, string author)
6-
{
7-
Name = name;
8-
Author = author;
9-
}
1+
namespace IEnumerableCSharp;
102

11-
public string Name { get; set; }
12-
public string Author { get; set; }
13-
}
14-
}
3+
public record Book(string Name, string Author);
Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,35 @@
11
using System.Collections;
22

3-
namespace IEnumerableCSharp
3+
namespace IEnumerableCSharp;
4+
5+
public class BookEnumerator : IEnumerator
46
{
5-
public class BookEnumerator : IEnumerator
6-
{
7-
private readonly Book[] _books;
8-
private int _index = -1;
7+
private readonly Book[] _books;
8+
private int _index = -1;
99

10-
public BookEnumerator(Book[] books)
11-
{
12-
_books = books;
13-
}
10+
public BookEnumerator(Book[] books)
11+
{
12+
_books = books;
13+
}
1414

15-
public Book Current
15+
public Book Current
16+
{
17+
get
1618
{
17-
get
18-
{
19-
return _books[_index];
20-
}
19+
return _books[_index];
2120
}
21+
}
2222

23-
object IEnumerator.Current => Current;
23+
object IEnumerator.Current => Current;
2424

25-
public bool MoveNext()
26-
{
27-
_index++;
28-
return _index < _books.Length;
29-
}
25+
public bool MoveNext()
26+
{
27+
_index++;
28+
return _index < _books.Length;
29+
}
3030

31-
public void Reset()
32-
{
33-
_index = -1;
34-
}
31+
public void Reset()
32+
{
33+
_index = -1;
3534
}
3635
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using System.Collections;
2+
3+
namespace IEnumerableCSharp;
4+
5+
public class GenericLibrary : IEnumerable<Book>
6+
{
7+
private readonly Book[] _books;
8+
9+
public GenericLibrary(Book[] books)
10+
{
11+
_books = [.. books];
12+
}
13+
14+
public IEnumerator<Book> GetEnumerator()
15+
{
16+
foreach (var book in _books)
17+
{
18+
yield return book;
19+
}
20+
}
21+
22+
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
23+
}

‎collections-csharp/IEnumerableCSharp/IEnumerableCSharp/IEnumerableCSharp.csproj‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
5-
<TargetFramework>net7.0</TargetFramework>
5+
<TargetFramework>net10.0</TargetFramework>
66
<ImplicitUsings>enable</ImplicitUsings>
77
<Nullable>enable</Nullable>
88
</PropertyGroup>
Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,17 @@
11
using System.Collections;
22

3-
namespace IEnumerableCSharp
3+
namespace IEnumerableCSharp;
4+
5+
public class Library : IEnumerable
46
{
5-
public class Library : IEnumerable
6-
{
7-
private readonly Book[] _books;
7+
private readonly Book[] _books;
88

9-
public Library(Book[] books)
10-
{
11-
_books = new Book[books.Length];
9+
public Library(Book[] books)
10+
{
11+
_books = [.. books];
12+
}
1213

13-
for (int i = 0; i < books.Length; i++)
14-
{
15-
_books[i] = books[i];
16-
}
17-
}
14+
public BookEnumerator GetEnumerator() => new BookEnumerator(_books);
1815

19-
public BookEnumerator GetEnumerator() => new BookEnumerator(_books);
20-
21-
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
22-
23-
}
16+
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
2417
}
Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,26 @@
1-
namespace IEnumerableCSharp
1+
using IEnumerableCSharp;
2+
3+
Book[] books =
4+
[
5+
new("Anna Karenina", "Leo Tolstoy"),
6+
new("To Kill a Mockingbird", "Harper Lee"),
7+
new("The Great Gatsby", "F. Scott Fitzgerald"),
8+
new("One Hundred Years of Solitude", "Gabriel García Márquez"),
9+
new("A Passage to India", "E.M. Forster")
10+
];
11+
12+
var library = new Library(books);
13+
14+
foreach (var book in library)
215
{
3-
internal class Program
4-
{
5-
static void Main(string[] args)
6-
{
7-
var books = new Book[5]
8-
{
9-
new Book("Anna Karenina", "Leo Tolstoy"),
10-
new Book("To Kill a Mockingbird", "Harper Lee"),
11-
new Book("The Great Gatsby", "F. Scott Fitzgerald"),
12-
new Book("One Hundred Years of Solitude", "Gabriel García Márquez"),
13-
new Book("A Passage to India", "E.M. Forster")
14-
};
16+
Console.WriteLine($"Book: {book.Name}, Author: {book.Author}");
17+
}
1518

16-
var library = new Library(books);
19+
var genericLibrary = new GenericLibrary(books);
1720

18-
foreach (var book in library)
19-
{
20-
Console.WriteLine($"Book: {book.Name}, Author: {book.Author}");
21-
}
22-
}
23-
}
24-
}
21+
var tolstoy = genericLibrary.Where(book => book.Author == "Leo Tolstoy");
22+
23+
foreach (var book in tolstoy)
24+
{
25+
Console.WriteLine($"By Tolstoy: {book.Name}");
26+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using System.Collections;
2+
using IEnumerableCSharp;
3+
4+
namespace Tests;
5+
6+
public class LibraryTests
7+
{
8+
private static readonly Book[] Books =
9+
[
10+
new("Anna Karenina", "Leo Tolstoy"),
11+
new("To Kill a Mockingbird", "Harper Lee"),
12+
new("War and Peace", "Leo Tolstoy")
13+
];
14+
15+
[Fact]
16+
public void WhenIteratingLibrary_ThenEveryBookComesBackInOrder()
17+
{
18+
var names = new List<string>();
19+
20+
foreach (var book in new Library(Books))
21+
{
22+
names.Add(book.Name);
23+
}
24+
25+
Assert.Equal(["Anna Karenina", "To Kill a Mockingbird", "War and Peace"], names);
26+
}
27+
28+
[Fact]
29+
public void WhenUsingLinqOnNonGenericLibrary_ThenCastIsNeeded()
30+
{
31+
var tolstoy = new Library(Books).Cast<Book>().Where(book => book.Author == "Leo Tolstoy");
32+
33+
Assert.Equal(2, tolstoy.Count());
34+
}
35+
36+
[Fact]
37+
public void WhenUsingLinqOnGenericLibrary_ThenNoCastIsNeeded()
38+
{
39+
var tolstoy = new GenericLibrary(Books).Where(book => book.Author == "Leo Tolstoy");
40+
41+
Assert.Equal(2, tolstoy.Count());
42+
}
43+
44+
[Fact]
45+
public void WhenResettingIteratorEnumerator_ThenNotSupportedExceptionIsThrown()
46+
{
47+
using var enumerator = new GenericLibrary(Books).GetEnumerator();
48+
49+
Assert.Throws<NotSupportedException>(() => enumerator.Reset());
50+
}
51+
}
Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,28 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net7.0</TargetFramework>
4+
<TargetFramework>net10.0</TargetFramework>
55
<ImplicitUsings>enable</ImplicitUsings>
66
<Nullable>enable</Nullable>
77

88
<IsPackable>false</IsPackable>
99
</PropertyGroup>
1010

1111
<ItemGroup>
12-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
13-
<PackageReference Include="xunit" Version="2.4.1" />
14-
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
12+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.11.0" />
13+
<PackageReference Include="xunit" Version="2.9.3" />
14+
<PackageReference Include="xunit.runner.visualstudio" Version="4.0.1">
1515
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
1616
<PrivateAssets>all</PrivateAssets>
1717
</PackageReference>
18-
<PackageReference Include="coverlet.collector" Version="3.1.2">
18+
<PackageReference Include="coverlet.collector" Version="10.1.0">
1919
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
2020
<PrivateAssets>all</PrivateAssets>
2121
</PackageReference>
2222
</ItemGroup>
2323

24+
<ItemGroup>
25+
<ProjectReference Include="../IEnumerableCSharp/IEnumerableCSharp.csproj" />
26+
</ItemGroup>
27+
2428
</Project>

0 commit comments

Comments
 (0)