C#12中的Collection expressions(集合表示式語法糖)

2023-11-20 12:05:11

C#12中引入了新的語法糖來建立常見的集合。並且可以使用..來解構集合,將其內聯到另一個集合中。

支援的型別

  • 陣列型別,例如 int[]。
  • System.Span<T> 和 System.ReadOnlySpan<T>。
  • 支援常見泛型集合,例如 System.Collections.Generic.List<T>。

集合表示式使用

以下展示瞭如何使用集合表示式

static void Main(string[] args)
{
    List<string> names1 = ["one", "two"];
    List<string> names2 = ["three", "four"];
    List<List<string>> names3 = [["one", "two"], ["three", "four"]];
    List<List<string>> names4 = [names1, names2];
}

可以看出使用方法十分簡單

 

集合表示式解構

在C#12中通過..即可將一個集合解構,並將其作為另一個集合的元素。

static void Main(string[] args)
{
    List<string> names1 = ["one", "two"];
    List<string> names2 = ["three", "four"];
    List<string> name = [.. names1, .. names2];
}

 

自定義型別支援集合表示式

型別通過編寫 Create() 方法,和對集合型別應用System.Runtime.CompilerServices.CollectionBuilderAttribute 選擇加入集合表示式支援。以下是個例子

[CollectionBuilder(typeof(LineBufferBuilder), "Create")]
public class LineBuffer : IEnumerable<char>
{
    private readonly char[] _buffer = new char[80];

    public LineBuffer(ReadOnlySpan<char> buffer)
    {
        int number = (_buffer.Length < buffer.Length) ? _buffer.Length : buffer.Length;
        for (int i = 0; i < number; i++)
        {
            _buffer[i] = buffer[i];
        }
    }

    public IEnumerator<char> GetEnumerator() => _buffer.AsEnumerable<char>().GetEnumerator();
    IEnumerator IEnumerable.GetEnumerator() => _buffer.GetEnumerator();
}

internal static class LineBufferBuilder
{
    internal static LineBuffer Create(ReadOnlySpan<char> values) => new LineBuffer(values);
}

internal class Program
{
    static void Main(string[] args)
    {
        LineBuffer line = ['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!'];
    }
}

首先,需要建立一個包含 Create 方法的類:LineBufferBuilder。LineBufferBuilder.Create方法必須返回 LineBuffer 物件,並且必須採用 ReadOnlySpan<char> 型別的單個引數。 

最後,必須將 CollectionBuilderAttribute新增到 LineBuffer 類宣告。其中,第一個引數提供生成器類的名稱, 第二個特性提供生成器方法的名稱。

這樣一個自定義的類就可以支援集合表示式了。