Я практикуюсь в C# и отказался от метода Add() для реализации простого связанного списка, показанного ниже. Я посмотрел на ответ и не могу понять одну вещь. Он присваивает переменной current_node значение «этот», переходит к последнему узлу и делает новый последний узел «следующим» из последнего узла. Но тогда как current_node связан с "this", так как я не вижу в коде никаких действий по эффекту "this.next = current_node"?
Кроме того, правильно ли мой комментарий относительно метода GetEnumerator(), что он автоматически вызывается, если сам класс (т.е. не методы внутри класса) передается в метод, который ожидает вывод IEnumerable<T>, например как XUnit 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();
}
}
Некоторые модульные тесты для кода:
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);
}
}
Отвечает ли это на ваш вопрос? Когда вы используете ключевое слово this? и Что означает слово this в C# и Какова цель ключевого слова this в C# и В C# требуется ли ключевое слово this?
Вы читаете код задом наперед. Он «присваивает
this
current_node
». Вы не можете присвоить что-либо "наthis
"Ключевое слово
this
предназначено для управления текущим экземпляром с точки зрения кода экземпляра объекта класса. Например, наличиеSimpleLinkedList<Something> instance;
здесьthis
равно самомуinstance
внутри класса. Это все. См. предлагаемые дубликаты для причин и использования.Где в коде «this.next = current_node»? Или, может быть, вы считаете, что он должен быть там?