之前,想把一个对象当集合使用,需要给这个类型构建索引器,为了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万倍,虽然单次调用耗时可以忽略,但有时这个功能放在大循环中,累加起来的这些时间就不能忽视了。
文章来源微信公众号
想要更快更方便的了解相关知识,可以关注微信公众号