深入浅析C# 11 对 ref 和 struct 的改进

深入浅析C# 11 对 ref 和 struct 的改进

简介

C# 11 是微软新推出的一项编程语言的更新版本,其中包含了对于 ref 和 struct 的一些优化改进。此次改进旨在提高代码的运行效率并降低代码运行的堆内存的占用。为了能够更好地理解这些改进,需要先了解 ref 和 struct 的相关知识。

ref 和 struct

在 C# 中,ref 和 struct 都是比较重要的概念。ref 是 C# 中的一种引用类型,它使得在函数中可以直接对变量进行修改,而不需要进行复制,提高了代码的运行效率;而 struct 是一种值类型,可以被看作是一种轻量级的类,实例的分配不需要用到堆,减少了堆内存的使用。

C# 11 对 ref 和 struct 的改进

Span 结构体的支持

Span 是 C# 7 引入的一种结构体,但在 C# 11 中,其得到了更多的扩展。Span 不占用堆内存,其作用是“暴力”化简代码,并且可以更好地规避内存泄漏的风险。通过对其进行改进,使其在 ref / in 形式中提供更多的支持。

示例 1:以下代码使用 Span 进行内存拷贝:

int[] array = new int[] {1, 2, 3, 4, 5};
Span<int> span = array;
Span<int> subSpan = span.Slice(start: 2, length: 2);
int[] newArray = subSpan.ToArray();

示例 2:以下代码使用 Span 进行缓冲区写入操作:

using System.Buffers;

const int size = 1024;
using var memoryPool = MemoryPool<byte>.Shared;
using var rented = memoryPool.Rent(size);
try
{
    var memory = rented.Memory;
    var span = memory.Span;
    FillBuffer(span);
    ProcessBufferNew(ref MemoryMarshal.GetReference(span), span.Length);

    void FillBuffer(Span<byte> buffer)
    {
        for (int i = 0; i < buffer.Length; i++)
        {
            buffer[i] = (byte)i;
        }
    }

    unsafe void ProcessBufferNew(ref byte startRef, int length)
    {
        fixed (byte* ptr = &startRef)
        {
            // 使用指针 ptr 进行读写操作
        }
    }
}
finally
{
    memoryPool.Return(rented);
}

ref struct 和 readonly struct 的扩展

在 C# 11 中,ref struct 和 readonly struct 的限制得到了进一步的放松。现在,可以在这些结构体中添加实例字段(以前只能添加静态字段),并将它们作为方法的返回值和参数使用。

示例 3:以下代码展示了如何将 ref struct 作为参数传递,并以 ref 返回值的形式计算它们的总和。

ref struct Log
{
    public void LogStatus(string msg) { /* implement */ }
    public int TotalErrors { get; private set; }

    // added fields in C# 11
    private int ErrorCount;
    private int WarnCount;
    public void LogError() => ++ErrorCount;
    public void LogWarning() => ++WarnCount;    
}

void UsingRefStruct(in Log log, ref int totalErrors)
{
    log.LogStatus("Processing logs...");

    for (int i = 0; i < 100; i++)
    {
        // process log entry
        if (i == 25) log.LogError();
        if (i == 52) log.LogWarning();
    }

    log.LogStatus("Processing complete.");
    totalErrors = log.TotalErrors;
}

ref struct ErrorInfo
{
    public readonly string Message;
    public readonly DateTime TimeStamp;    
}

ref ErrorInfo GetErrorInfo()
{
    return new ErrorInfo { Message = "Error message", TimeStamp = DateTime.Now };
}

结语

C# 11 的改进使得在代码运行的过程中,结构体和引用类型的使用更加灵活,同时可以占用更少的内存。通过使用示例代码,实际操作一定会给开发者们带来更好的理解。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:深入浅析C# 11 对 ref 和 struct 的改进 - Python技术站

(0)
上一篇 2023年6月6日
下一篇 2023年6月6日

相关文章

  • C#基础知识之new关键字介绍

    下面是关于” C#基础知识之new关键字介绍”的完整攻略: 什么是new关键字 在C#中,new关键字有两种不同的用法。一种是用来创建新的对象,另一种是用来隐藏基类中的同名成员。 创建新的对象 当我们创建一个新的对象时,需要使用new关键字和构造函数。构造函数是一个类中的特殊方法,用于初始化新对象的所有字段和属性。以下是一个简单的示例: public cla…

    C# 2023年5月31日
    00
  • 浅谈ASP.NET Core的几种托管方式

    浅谈ASP.NET Core的几种托管方式 ASP.NET Core是一个跨平台的Web应用程序框架,可以在Windows、Linux和macOS上运行。在ASP.NET Core中,有几种不同的托管方式可供选择。本攻略将介绍ASP.NET Core的几种托管方式,并提供两个示例说明。 IIS托管 IIS是Windows操作系统中的Web服务器,可以使用II…

    C# 2023年5月16日
    00
  • C# Directory.GetParent(string path):获取指定目录的父级目录路径

    Description(作用): Directory.GetParent(string path)方法实现了获取指定路径的上一级目录路径。即,可以获取给定路径的父文件夹的路径。 Usage(使用方法): 该方法属于System.IO命名空间,因此在调用该方法前先引用该命名空间。 该方法的语法如下: public static DirectoryInfo Ge…

    C# 2023年4月19日
    00
  • .NET Core 依赖注入

    在.NET Core中,依赖注入(Dependency Injection,简称DI)是框架的一个重要特性,可以帮助我们解耦代码、管理对象生命周期以及提高可测试性等.一下是.NET Core中依赖注入的一些基本概念和用法:   1、服务(Service):在DI中,服务即一个对象或者类型。用于完成特定的功能.例如,数据库访问、日志记录等都可以看作一个服务  …

    C# 2023年4月24日
    00
  • C#实现调用迅雷下载的方法

    让我们来分步骤地讲解如何使用C#实现调用迅雷下载的方法。 步骤一:了解调用迅雷协议 迅雷软件是支持HTTP、FTP和ED2K等协议的下载工具,而它还提供了一套自己的迅雷协议,可以通过这个协议实现与迅雷软件的交互。 在C#中,我们可以使用以下格式的URL来调用迅雷下载的方法: thunder://QUFmdHA6Ly9kZG5zLmdvb2dsZS5jb20v…

    C# 2023年5月15日
    00
  • C#判断一个图像是否是透明的GIF图的方法

    判断一个图像是否是透明的GIF图是一个常见的需求,下面将介绍如何使用C#语言实现。 1. 判断图像中是否存在透明像素 一张GIF图像通常会包含多个帧,因此我们首先需要遍历每一个帧,并对每一个帧进行透明像素检查。 using System.Drawing; using System.Drawing.Imaging; public static bool IsT…

    C# 2023年6月1日
    00
  • c# 开发语音识别程序

    C#开发语音识别程序 概述 语音识别是当前比较热门的领域之一,它可以应用在语音助手、音频转写等领域。本文主要介绍如何使用C#开发语音识别程序。 准备工作 在使用C#开发语音识别程序之前,我们需要安装语音识别的开发库。我们可以使用Microsoft Speech Platform SDK 11来实现对语音的识别,这个库在Windows 7以及之后的版本中默认已…

    C# 2023年6月6日
    00
  • golang判断结构体为空的问题

    判断一个结构体变量是否为空,首先要定义什么叫做一个空的结构体变量。通常来说,我们认为一个结构体变量只有所有成员变量的值都等于其类型的零值时,才认为是一个空的结构体变量。 在Go语言中,结构体类型是值类型,因此如果一个结构体变量没有经过初始化,那么其所有成员变量的值都会等于其类型的零值。如果我们想要判断一个结构体变量是否为空,那么最简单的方法就是判断其所有成员…

    C# 2023年6月6日
    00
合作推广
合作推广
分享本页
返回顶部