Skip to content

Commit

Permalink
Modernise snippets showing use of generics in C#
Browse files Browse the repository at this point in the history
Use some newer language features to increase the signal/noise ratio in code samples used to describe generics in C#.

- Make code shorter through auto properties.
- Narrow scope of <Snippet> areas to remove boilerplate.
- Use target-typed new.
- Remove redundant constructor.

Note we could go further with the language features here (such as collection initializers) but as this seems like a very fundamental level article I thought it best to use more explicit forms.

These snippets are used in https://review.learn.microsoft.com/en-us/dotnet/csharp/fundamentals/types/generics?branch=main
  • Loading branch information
drewnoakes authored Nov 20, 2024
1 parent e2d83bb commit ce358ef
Showing 1 changed file with 32 additions and 50 deletions.
82 changes: 32 additions & 50 deletions docs/csharp/fundamentals/types/snippets/generics/Program.cs
Original file line number Diff line number Diff line change
@@ -1,86 +1,66 @@
namespace generics
namespace generics
{
//---------------------------------------------------------------------------
//<Snippet1>
// Declare the generic class.
public class GenericList<T>
{
public void Add(T input) { }
public void Add(T item) { }
}

public class ExampleClass { }

class TestGenericList
{
private class ExampleClass { }
static void Main()
{
// Declare a list of type int.
GenericList<int> list1 = new GenericList<int>();
// Create a list of type int.
GenericList<int> list1 = new();
list1.Add(1);

// Declare a list of type string.
GenericList<string> list2 = new GenericList<string>();
// Create a list of type string.
GenericList<string> list2 = new();
list2.Add("");

// Declare a list of type ExampleClass.
GenericList<ExampleClass> list3 = new GenericList<ExampleClass>();
// Create a list of type ExampleClass.
GenericList<ExampleClass> list3 = new();
list3.Add(new ExampleClass());
}
}
//</Snippet1>
namespace SecondExample
{
//<Snippet2>
// type parameter T in angle brackets
// Type parameter T in angle brackets.
public class GenericList<T>
{
// The nested class is also generic on T.
private class Node
// The nested class is also generic, and
// holds a data item of type T.
private class Node(T t)
{
// T used in non-generic constructor.
public Node(T t)
{
next = null;
data = t;
}

private Node? next;
public Node? Next
{
get { return next; }
set { next = value; }
}

// T as private member data type.
private T data;
// T as property type.
public T Data { get; set; } = t;

// T as return type of property.
public T Data
{
get { return data; }
set { data = value; }
}
public Node? Next { get; set; }
}

// First item in the linked list
private Node? head;

// constructor
public GenericList()
{
head = null;
}

// T as method parameter type:
// T as parameter type.
public void AddHead(T t)
{
Node n = new Node(t);
Node n = new(t);
n.Next = head;
head = n;
}

// T in method return type.
public IEnumerator<T> GetEnumerator()
{
Node? current = head;

while (current != null)
while (current is not null)
{
yield return current.Data;
current = current.Next;
Expand All @@ -92,27 +72,29 @@ public IEnumerator<T> GetEnumerator()
namespace ThirdExample
{
using SecondExample;
//<Snippet3>
class TestGenericList
{
static void Main()
{
// int is the type argument
GenericList<int> list = new GenericList<int>();
//<Snippet3>
// A generic list of int.
GenericList<int> list = new();

// Add ten int values.
for (int x = 0; x < 10; x++)
{
list.AddHead(x);
}

// Write them to the console.
foreach (int i in list)
{
System.Console.Write(i + " ");
Console.WriteLine(i);
}
System.Console.WriteLine("\nDone");

Console.WriteLine("Done");
//</Snippet3>
}
}
//</Snippet3>
}

}

0 comments on commit ce358ef

Please sign in to comment.