接下来,我们再实现一个 ColorView
,允许以多种方式对 Color
进行访问和修改:
public ref struct ColorView{private readonly ref Color color;public ColorView(ref Color color){this.color = ref color;}[DoesNotReturn] private static ref byte ThrowOutOfRange() => throw new IndexOutOfRangeException();public ref byte R => ref color.R;public ref byte G => ref color.G;public ref byte B => ref color.B;public ref byte A => ref color.A;public ref uint Rgba => ref Unsafe.As<Color, uint>(ref color);public ref byte this[int index]{get{switch (index){case 0:return ref color.R;case 1:return ref color.G;case 2:return ref color.B;case 3:return ref color.A;default:return ref ThrowOutOfRange();}}}public ColorViewEnumerator GetEnumerator(){return new(this);}public ref struct ColorViewEnumerator{private readonly ColorView view;private int index;public ref byte Current => ref view[index];public ColorViewEnumerator(ColorView view){this.index = -1;this.view = view;}public bool MoveNext(){if (index >= 3) return false;index++;return true;}}}
然后我们给 Color
添加一个 CreateView()
方法即可:
public ColorView CreateView() => new(ref this);
如此一来,我们便能够轻松地通过不同视图来操作 Color
数据,并且一切抽象都是零开销的:
Color color = new(255, 128, 42, 137);ColorView view = color.CreateView();Console.WriteLine(color); // Color { R = 255, G = 128, B = 42, A = 137 }view.R = 7;view[3] = 28;Console.WriteLine(color); // Color { R = 7, G = 128, B = 42, A = 28 }view.Rgba = 3072;Console.WriteLine(color); // Color { R = 0, G = 12, B = 0, A = 0 }foreach (ref byte i in view) i++;Console.WriteLine(color); // Color { R = 1, G = 13, B = 1, A = 1 }
后记C# 是一门自动挡手动挡同时具备的语言,上限极高的同时下限也极低 。可以看到上面的几个例子中,尽管封装所需要的代码较为复杂,但是到了使用的时候就如同一切的底层代码全都消失了一样,各种语法糖加持之下,不仅仅用起来非常的方便快捷,而且借助零开销抽象,代码的内存效率和运行效率都能达到 C++、Rust 的水平 。此外,现在的 .NET 7 有了 NativeAOT 之后更是能直接编译到本机代码,运行时无依赖也完全不需要虚拟机,实现了与 C++、Rust 相同的应用形态 。这些年来 .NET 在不同的平台、不同工作负载上均有着数一数二的运行效率表现的理由也是显而易见的 。
而代码封装的脏活则是由各库的作者来完成的,大多数人在进行业务开发时,无需接触和关系这些底层的东西,甚至哪怕什么都不懂都可以轻松使用封装好的库,站在这些低开销甚至零开销的抽象基础之上来进行应用的构建 。
以上便是对 .NET 中进行零开销抽象的一些简单介绍,在开发中的局部热点利用这些技巧能够大幅度提升运行效率和内存效率 。
经验总结扩展阅读
- 二、.Net Core搭建Ocelot
- 一千零一夜柏海的结局是什么?
- 创建.NET程序Dump的几种姿势
- 中国6大奇葩零食排行榜
- 干无花果怎么吃
- 零食可以托运吗
- C# 8.0 添加和增强的功能【基础篇】
- .NET性能系列文章二:Newtonsoft.Json vs. System.Text.Json
- 某 .NET RabbitMQ SDK 有采集行为,你怎么看?
- .net core Blazor+自定义日志提供器实现实时日志查看器