C#12:内联数组

之前,想把一个对象当集合使用,需要给这个类型构建索引器,为了foreach,还需要实现IEnumerable。.

public struct Season : IEnumerable{    readonly string[] _arr;    public Season()    {        _arr = new string[4];    }    public string this[int index]    {        get => _arr[index];        set => _arr[index] = value;    }    public IEnumerator GetEnumerator()    {        for (var i = 0; i < _arr.Length; i++)        {            yield return _arr[i];        }    }}

使用时,初始化,给每个元素赋值即可,然后就可以调用foreach来循环了。

var season = new Season();season[0] = "春";season[1] = "夏";season[2] = "秋";season[3] = "冬";foreach (var s in season){    Console.WriteLine(s);}

C#12引入了内联数组,让使用更简单,使用前,需要using ystem.Runtime.CompilerServices命名空间,然后内联数组定义如下:

[InlineArray(4)]public struct Season{    private string _name;}

使用方式无变化,并且内联数组性能更好,原因具体参照官方说明。

var season = new Season();season[0] = "春";season[1] = "夏";season[2] = "秋";season[3] = "冬";foreach (var s in season){    Console.WriteLine(s);}

下面用BenchmarkDotNet来做个性能对比吧,完整代码如下:

using BenchmarkDotNet.Attributes;using BenchmarkDotNet.Running;using System.Collections;using System.Runtime.CompilerServices;
BenchmarkRunner.Run<Demo1>();
public class Demo1{    Season0 season0;    Season1 season1;    [GlobalSetup]    public void Setup()    {        season0 = new Season0();        season0[0] = "春";        season0[1] = "夏";        season0[2] = "秋";        season0[3] = "冬";
        season1 = new Season1();        season1[0] = "春";        season1[1] = "夏";        season1[2] = "秋";        season1[3] = "冬";    }

    [Benchmark()]    public void P0()    {        foreach (var s in season0)        {            var s0 = s;            //Console.WriteLine(s);        }    }
    [Benchmark]    public void P1()    {        foreach (var s in season1)        {            var s0 = s;            //Console.WriteLine(s);        }    }}
[InlineArray(4)]public struct Season0{    private string _name;}
public struct Season1 : IEnumerable{    readonly string[] _arr;    public Season1()    {        _arr = new string[4];    }    public string this[int index]    {        get => _arr[index];        set => _arr[index] = value;    }    public IEnumerator GetEnumerator()    {        for (var i = 0; i < _arr.Length; i++)        {            yield return _arr[i];        }    }}

下图是最后的对比结果,当然这是一个很粗糙的对比,但从性能上来看,内联数组不只要强数10万倍,虽然单次调用耗时可以忽略,但有时这个功能放在大循环中,累加起来的这些时间就不能忽视了。

C#12:内联数组