C# 将“当前”属性添加到从 list<T> 继承的列表类

问题描述

我想将“Current”属性添加到我的列表类 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
    {

    }
}

我想添加“当前”属性/方法以便像这样使用它:

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 类和一个 Main 方法,显示了用法示例。您可以使用 Linq 获取卷列表中的第一个/最后一个项目,然后您可以使用 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",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 字段,用于跟踪您正在使用的项目。它与集合/列表的索引有关。

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,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",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",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",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",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());
        }
    }
}