I'm practicing c# and gave up on making the Add() method for an implementation of a simple linked list shown below. I looked up at the answer and can't understand one thing. It assigns the variable current_node to "this", goes to the last node and makes a new last node as the "next" of the last node. But then how is current_node related to "this", since I don't see any action to the effect of "this.next = current_node" in the code?
In addition, is my comment correct regarding the GetEnumerator() method, that it is automatically called if the class itself (i.e. not the methods inside the class) is passed into a method that expects an output of IEnumerable<T>, such as XUnit's Assert.Equal()?
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public class SimpleLinkedList<T> : IEnumerable<T>
{
private T value;
private SimpleLinkedList<T> next;
// START READING HERE, THESE TWO METHODS DEFINE THE LIST
// "this" refers to the linked list itself.
// Two constructors mean that the class can take
// either a single input of type T or a collection of type T
// that implements IEnumerable.
public SimpleLinkedList(T value) => this.value = value;
public SimpleLinkedList(IEnumerable<T> values)
{
this.value = values.First();
foreach (var i in values.Skip(1))
{
this.Add(i);
}
}
public T Value
{
get
{
return this.value;
}
}
public SimpleLinkedList<T> Next
{
get
{
return this.next;
}
}
public SimpleLinkedList<T> Add(T value)
{
var current_node = this;
while (current_node.next != null)
{
current_node = current_node.next;
}
current_node.next = new SimpleLinkedList<T>(value);
return this;
}
// This method is automatically called if the class itself
// (i.e. not the methods inside the class) is passed into a
// method that expects an output of IEnumerable<T>,
// such as XUnit's Assert.Equal().
public IEnumerator<T> GetEnumerator()
{
yield return value;
var current_node = this.next;
while (current_node != null)
{
yield return current_node.value;
current_node = current_node.next;
}
}
// Since we use Inenumerable<T> interface, need to also implement the
// non-generic GetEnumerator() method for backwards compatibilty with previous
// .net versions.
// Just make this method return the generic GetEnumerator() method.
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
Some of the unit tests for the code are:
using System.Linq;
using Xunit;
public class SimpleLinkedListTests
{
[Fact]
public void Single_item_list_value()
{
var list = new SimpleLinkedList<int>(1);
Assert.Equal(1, list.Value);
}
[Fact(Skip = "Remove this Skip property to run this test")]
public void Single_item_list_has_no_next_item()
{
var list = new SimpleLinkedList<int>(1);
Assert.Null(list.Next);
}
[Fact]
public void Two_item_list_first_value()
{
var list = new SimpleLinkedList<int>(2).Add(1);
Assert.Equal(2, list.Value);
}
[Fact(Skip = "Remove this Skip property to run this test")]
public void Two_item_list_second_value()
{
var list = new SimpleLinkedList<int>(2).Add(1);
Assert.Equal(1, list.Next.Value);
}
[Fact(Skip = "Remove this Skip property to run this test")]
public void Two_item_list_second_item_has_no_next()
{
var list = new SimpleLinkedList<int>(2).Add(1);
Assert.Null(list.Next.Next);
}
[Fact]
public void Implements_enumerable()
{
var values = new SimpleLinkedList<int>(2).Add(1);
Assert.Equal(new[] { 2, 1 }, values);
}
[Fact]
public void From_enumerable()
{
var list = new SimpleLinkedList<int>(new[] { 11, 7, 5, 3, 2 });
Assert.Equal(11, list.Value);
Assert.Equal(7, list.Next.Value);
Assert.Equal(5, list.Next.Next.Value);
Assert.Equal(3, list.Next.Next.Next.Value);
Assert.Equal(2, list.Next.Next.Next.Next.Value);
}
[Theory(Skip = "Remove this Skip property to run this test")]
[InlineData(1)]
[InlineData(2)]
[InlineData(10)]
[InlineData(100)]
public void Reverse(int length)
{
var values = Enumerable.Range(1, length).ToArray();
var list = new SimpleLinkedList<int>(values);
var reversed = list.Reverse();
Assert.Equal(values.Reverse(), reversed);
}
[Theory(Skip = "Remove this Skip property to run this test")]
[InlineData(1)]
[InlineData(2)]
[InlineData(10)]
[InlineData(100)]
public void Roundtrip(int length)
{
var values = Enumerable.Range(1, length);
var listValues = new SimpleLinkedList<int>(values);
Assert.Equal(values, listValues);
}
}