C# 将 "Current" 属性 添加到继承自列表 <T> 的列表 class

C# Adding "Current" property to a list class inheriting from list<T>

我想将“当前”属性 添加到我的列表 class VolumeList。 这是我的代码:

class Volume
{
    private string name;
    private string color;
    private bool has_segment;

    public Volume(string Name, string color, bool has_segment)

    this.name = name;
    this.color = color;
    this.has_segment = has_segment;

  public string Name
    {
        get { return name; }
        set { name = value; }
    }

    public string Color
    {
        get { return color; }
        set { color = value; }
    }
    public bool HasSegment
    {
        get { return has_segment; }
        set { has_segment = value; }
    }
    public static ROOTList<Volume> VolumeList{ get; set; } = new ROOTList<Volume>();
}


public class ROOTList<T> : List<T>
{


    public T Last
    {
        get
        {
            return this[this.Count - 1];
        }
        set
        {
            this[this.Count - 1] = value;
        }
    }
    public T First
    {
        get
        {
            return this[0];
        }
        set
        {
            this[0] = value;
        }
    }

    public T Current
    {

    }
}

我想添加“当前”property/method 以便像这样使用它:

Volume.VolumeList.Current.Name (I get the name of the current volume)
Volume.VolumeList.Current.Name = "test" (I set the name "test" to the current volume).

First 和“Last` 方法有效。

请问有什么解决办法吗?

此致

关于如何执行此操作有几个选项。由于您刚刚开始,我会说使用选项 1,因为这要简单得多。

选项 1:基本使用 LINQ

下面是 Volume class 和 Main 方法,显示了用法示例。您可以使用 Linq 获取卷列表中的 first/last 项目,然后您可以使用 volumes[i] 设置列表中各个项目的属性,其中 i 是项目的索引列表。

您还可以使用 Linq 根据 ColorNameHasVolume 查找特定卷,然后使用 foreach 循环更改每个卷的属性。

此处提供有关 LINQ 的更多信息:https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/

看看下面的例子:

using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp1
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            var volumes = new List<Volume>();
            var volume1 = new Volume("vol1", "red", true);
            var volume2 = new Volume("vol2", "red", true);

            volumes.Add(volume1); //adds the first volume
            volumes.Add(volume2); //adds the second volume
            var lastVolume = volumes.First(); //gets the first volume
            var firstVolume = volumes.Last(); //gets the last volume
            volumes[0].Color = "blue"; //sets the first volume color to blue
            volumes[1].Color = "green"; //sets the second volume color to green

            // set all green volumes to purple
            var greenVolumes = volumes.Where(v => v.Color == "green");
            foreach (var greenVolume in greenVolumes)
            {
                greenVolume.Color = "purple";
            }
        }
    }

    public class Volume
    {
        public string Name { get; set; }
        public string Color { get; set; }
        public bool HasSegment { get; set; }

        public Volume(string name, string color, bool hasSegment)
        {
            Name = name;
            Color = color;
            HasSegment = hasSegment;
        }
    }
}

选项 2:使用迭代器模式更高级

在这里查看迭代器模式:https://www.dofactory.com/net/iterator-design-pattern

基本上,您可以通过选择 MoveNext()LastFirstCurrent 逐步浏览列表。我添加了一个 _current 字段来跟踪您正在使用的项目。它涉及到collection/list.

的索引
using System.Collections.Generic;

namespace WebApplication1.Sandbox
{
    public class Volume
    {
        public string Name { get; set; }
        public string Color { get; set; }
        public bool HasSegment { get; set; }

        public Volume(string name, string color, bool hasSegment)
        {
            Name = name;
            Color = color;
            HasSegment = hasSegment;
        }
    }

    public class Iterator<T>
    {
        private readonly List<T> _items;
        private int _index;

        public T Last
        {
            get => _items[_items.Count - 1];
            set => _items[_items.Count - 1] = value;
        }

        public T First
        {
            get => _items[0];
            set => _items[0] = value;
        }

        public T Current
        {
            get => _items[_index];
            set => _items[_index] = value;
        }

        public Iterator(List<T> items)
        {
            _items = items;
        }

        public bool MoveNext()
        {
            if (_index == _items.Count - 1)
            {
                return false;
            }
            else
            {
                _index++;
                return true;
            }
        }
    }
}

现在你可以像在这个单元测试中一样使用它了:

        [Fact]
        public void VolumeIteratorGetsNextThenSetsCurrentByProperty()
        {
            var sut = new Iterator<Volume>(_volumes);
            sut.MoveNext();
            sut.Current.Name = "vol2modifiedAgain";

            Assert.Equal("vol2modifiedAgain", sut.Current.Name);
        }

单元测试在这里:

using System.Collections.Generic;
using WebApplication1.Sandbox;
using Xunit;

namespace WebApplication1.Tests
{
    public class VolumeIteratorTests
    {
        private List<Volume> _volumes => new List<Volume>()
            {
                new Volume("vol1", "green", true),
                new Volume("vol2", "green", true)
            };

        [Fact]
        public void VolumeIteratorGetsCurrent()
        {
            var sut = new Iterator<Volume>(_volumes);

            Assert.Equal("vol1", sut.Current.Name);
        }

        [Fact]
        public void VolumeIteratorGetsNext()
        {
            var sut = new Iterator<Volume>(_volumes);
            sut.MoveNext();

            Assert.Equal("vol2", sut.Current.Name);
        }

        [Fact]
        public void VolumeIteratorGetsNextThenSetsCurrent()
        {
            var sut = new Iterator<Volume>(_volumes);
            sut.MoveNext();
            sut.Current = new Volume("vol2modified", "green", false);

            Assert.Equal("vol2modified", sut.Current.Name);
        }
        
        [Fact]
        public void VolumeIteratorGetsNextThenSetsCurrentByProperty()
        {
            var sut = new Iterator<Volume>(_volumes);
            sut.MoveNext();
            sut.Current.Name = "vol2modifiedAgain";

            Assert.Equal("vol2modifiedAgain", sut.Current.Name);
        }

        [Fact]
        public void VolumeIteratorGetsLast()
        {
            var sut = new Iterator<Volume>(_volumes);
            
            Assert.Equal("vol2", sut.Last.Name);
        }
        
        [Fact]
        public void VolumeIteratorSetsLast()
        {
            var sut = new Iterator<Volume>(_volumes);
            sut.Last = new Volume("last", "red", true);

            Assert.Equal("last", sut.Last.Name);
        }

        [Fact]
        public void VolumeIteratorGetsFirst()
        {
            var sut = new Iterator<Volume>(_volumes);

            Assert.Equal("vol1", sut.First.Name);
        }
        
        [Fact]
        public void VolumeIteratorSetsFirst()
        {
            var sut = new Iterator<Volume>(_volumes);
            sut.First = new Volume("first", "red", true);

            Assert.Equal("first", sut.First.Name);
        }
        
        [Fact]
        public void MoveNextReturnsTrueIfNotLastItem()
        {
            var sut = new Iterator<Volume>(_volumes);
            
            Assert.True(sut.MoveNext());
        }
        
        [Fact]
        public void MoveNextReturnsFalseIfLastItem()
        {
            var sut = new Iterator<Volume>(_volumes);
            sut.MoveNext();

            Assert.False(sut.MoveNext());
        }
    }
}