ASP.NET Core高效管理字符串集合
我们在开发 Web 项目时经常遇到需要管理各种来源的字符串集合(例如HTTP 标头、查询字符串、设置的值等)的情况。合理的管理这些字符串集合不仅可以减少出bug的几率,也能提高应用程序的性能。ASP.NET Core 为我们提供了一种特殊的只读结构体 StringValues,它旨在高效处理多个字符串值,使用单个内部对象来表示null、一个或多个字符串。 下面我们来简单的探讨一下StringValues。
Tip:以下文章以管理HTTP 标头的字符串集合为例来讲解,其他来源的字符串集合类似。
一、传统方式
对于字符串集合的管理,我们会想到使用数组来存储每个标头关键字的多个值。 这种方法看起来简单易懂,代码也容易编写,但是却会带来性能和字符串管理的复杂性问题。当我们使用数组存储标头值时,就会遇到内存分配增加的问题。 即使在不必要的情况下,存储单个值也需要分配一个数组,这样就出现内了存浪费,那么在大流量网络应用中就会出现很明显的性能问题。
用一个例子来讲解以下。在程序中我们添加一个 HeaderManager 类,这个类用来存储HTTP标头,代码如下:
public class HeaderManager
{private readonly Dictionary<string, string[]> _headers = [];public void AddHeader(string key, params string[] values){if (_headers.TryGetValue(key, out var existingValues)){var newValues = new string[existingValues.Length + values.Length];existingValues.CopyTo(newValues, 0);values.CopyTo(newValues, existingValues.Length);_headers[key] = newValues;}else{_headers[key] = values;}}
}
在上面的代码中,我们声明类型为 Dictionary<string, string[]>的私有字段 _headers,我们又定义了一个 AddHeader方法,它接收一个字符串类型的键key以及一个使用 params关键字标记的数量可变的字符串值values。 接着我们使用 TryGetValue方法来检查字典 _headers中是否已包含指定的键,如果键存在就会创建一个新数组将现有值和新值合并起来,最后我们用合并后的数组更新字典。
传统方式使用 Dictionary<string, string[]>类型的变量来存储标头值,当添加新值时分配一个新的数组,然后复制现有值并添加新值。这种方法虽然简单明了,但频繁调整数组大小会导致内存分配增加从而造成性能问题。
二、使用 NameValueCollection
NameValueCollection允许我们在单个键下存储多个值。我们来修改一下前一小节的代码:
public class HeaderManager
{private readonly NameValueCollection _headers = [];public void AddHeader(string key, params string[] values){foreach (var value in values){_headers.Add(key, value);}}
}
在代码中,我们声明一个类型为 NameValueCollection的字段 _headers,在AddHeader方法中遍历 values数组,并将其添加到具有指定键的 _headers 集合中。NameValueCollection简化了标头管理,但由于内部要处理数组,因此也需要分配更多内存。
三、使用 StringValues
在 ASP.NET Core 中的许多核心组件和中间件都使用StringValues来管理字符串集合。StringValues是 struct类型(值类型),值类型是存储在堆栈中的,因此它与堆分配相比值类型的分配和取消分配速度更快,这又减少了内存的分配,进而降低了对垃圾回收的需求。StringValues对象可以存储null值、单个字符串和字符串数组。它使用单个对象来存储值,可帮助我们的项目减少内存分配,从而提高应用程序性能。 下面我们一起来看一下如何使用吧。
3.1 安装
要使用 StringValues就要安装Primitives软件包,在命令行输入如下代码即可安装:
dotnet add package Microsoft.Extensions.Primitives
3.2 使用
-
包含单个字符串的
StringValues:StringValues singleValue = new StringValues("value1");在上面代码中,我们使用了
StringValues的构造函数传入字符串初始化StringValues对象。这个构造函数创建的对象可以有效地存储单个字符串而不需分配数组。 -
让我们用字符串数组初始化
StringValues对象:StringValues multipleValues = new StringValues(new[] { "value1", "value2" });在上面代码中,我们使用
StringValues的数组构造函数,用字符串数组进行初始化。 当我们需要处理字符串集合时就可以使用这个构造函数。 -
使用空值或 null 值初始化
StringValues对象:StringValues emptyValue = new StringValues(); StringValues nullValue = new StringValues((string)null);在上面代码中,我们使用空值和 null 值初始化
StringValues构造函数。 这个构造函数可处理无值的情况,确保StringValues能管理空或 null 输入。
3.3 StringValues 的隐式转换以及逗号分隔字符串表示法
StringValues支持从单个字符串或字符串数组的隐式转换,方便我们初始化。当StringValues包含多个字符串时,它可以将它们表示为单个逗号分隔的字符串,代码如下:
StringValues implicitSingle = "value1";
Console.WriteLine($"隐式转换单个字符串: {implicitSingle}");
StringValues implicitMultiple = new[] { "value1", "value2" };
Console.WriteLine($"隐式转换多个字符串集合 : {implicitMultiple}");
StringValues values = new StringValues(new[] { "value1", "value2" });
Console.WriteLine($"逗号分隔值: {values}");
输出结果如下:

在上面代码中,当单个字符串被隐式转换为 StringValues`` 时它会直接显示该字符串,对于字符数组会转换为 StringValues```对象,并以逗号分隔列表的形式显示。
3.4 StringValues 的使用
我们修改一开始编写的HeaderManager类,将这个类修改为使用StringValues实现管理字符串集合,代码如下:
public class HeaderManager
{private readonly Dictionary<string, StringValues> _headers = new();public void AddHeader(string key, params string[] values){if (_headers.TryGetValue(key, out var existingValues)){_headers[key] = StringValues.Concat(existingValues, new StringValues(values));}else{_headers[key] = new StringValues(values);}}
}
在上面代码中,我们声明一个 类型为 Dictionary<string, StringValues>的字段 _headers。 然后使用TryGetValue检查_headers字典中是否已包含键,如果键存在就使用 StringValues.Concat方法将新值连接到现有的 StringValues对象上,否则创建一个新的 StringValues实例并将其添加到字典中。
四、总结
在开发 Web 项目时,管理不同来源的字符串集合(如 HTTP 标头、查询字符串、设置值等)至关重要。传统方法使用数组或 NameValueCollection 来管理这些字符串,但这些方法存在性能和内存管理问题。特别是数组的频繁调整会导致不必要的内存分配,影响性能。
ASP.NET Core 提供了 StringValues 结构体,作为更高效的解决方案。StringValues 是一个只读的值类型,支持单个字符串、字符串数组以及空值(null)。它通过减少内存分配和垃圾回收需求,提升了应用程序性能。与传统方法相比,StringValues 能更有效地处理字符串集合,避免了内存浪费。
使用 StringValues 可以显著优化管理字符串集合的性能,特别是在高流量网络应用中,其优势更加明显。
相关文章:
ASP.NET Core高效管理字符串集合
我们在开发 Web 项目时经常遇到需要管理各种来源的字符串集合(例如HTTP 标头、查询字符串、设置的值等)的情况。合理的管理这些字符串集合不仅可以减少出bug的几率,也能提高应用程序的性能。ASP.NET Core 为我们提供了一种特殊的只读结构体 S…...
vm-tools的卸载重装,只能复制粘贴,无法拖拽文件!
开始 ubuntu22.04 LTSVMwareTools-10.3.25-20206839.tar.gzVMware Workstation 17 Pro 各种该尝试的配置都尝试了,比如: 1.开启复制粘贴拖拽; 2.VMware Tools拖拽失效; 3.解决VMware无法拖拽. 均没有奏效. 安装过程报错, 报错异常: The installation of VMware Tools 10.3.25…...
Docker 容器网络技术
Docker 容器网络技术 一、概述 Docker 容器技术在微服务架构和云原生应用中扮演着重要角色。容器的轻量化和快速启动特性,使得它们成为现代应用部署的首选。然而,容器的网络连接和管理是一个复杂的问题,尤其是当涉及到容器间通信时。Docker…...
C++ 起始帧数、结束帧数、剪辑视频
C 指定起始帧数、结束帧数、 剪辑视频 C 无法直接用H264,只能用avi编码格式 #include <iostream> #include <opencv2/opencv.hpp>int main() {// 读取视频:创建了一个VideoCapture对象,参数为摄像头编号std::string path &quo…...
【项目一】基于pytest的自动化测试框架———解读requests模块
解读python的requests模块 什么是requests模块基础用法GET与POST的区别数据传递格式会话管理与持久性连接处理相应结果应对HTTPS证书验证错误处理与异常捕获 这篇blog主要聚焦如何使用 Python 中的 requests 模块来实现接口自动化测试。下面我介绍一下 requests 的常用方法、数…...
升级Ubuntu内核的几种方法
注意: Ubuntu主线内核由 Ubuntu 内核团队提供,用于测试和调试目的。 它们不受支持且不适合生产使用。 仅当它们可以解决当前内核遇到的关键问题时,才应该安装它们。 1、手动下载deb文件升级内核 来源:kernel.ubuntu.com/main…...
Android绘制靶面,初步点击位置区域划分取值测试
自定义View: public class TargetView extends View {private Paint paint;private int[] radii {100, 250, 400, 550, 700}; // 五个圆的半径private int numberOfSegments 8;private int[][] regionValues; // 存储每个区域的值public TargetView(Context cont…...
【SpringBoot】调度和执行定时任务--Quartz(超详细)
Quartz 是一个功能强大的任务调度框架,广泛用于在 Java 应用程序中定时执行任务,同时它支持 Cron 表达式、持久化任务、集群等特性。以下是 Quartz 的详细使用教程,包括安装、基本概念、简单示例和高级功能。 1. 安装 Quartz 首先ÿ…...
低代码开发平台系统架构概述
概述 织信低代码开发平台(产品全称:织信Informat)是一款集成了应用设计、运行与管理的综合性平台。它提供了丰富的功能模块,帮助用户快速构建、部署和维护应用程序。织信低代码平台通过集成丰富的功能模块,为用户提供…...
源码编译llama.cpp 、ggml 后端启用自定义BLAS加速
源码编译llama.cpp 、ggml 后端启用自定义BLAS加速 我在llama.cpp 官网上提交了我的解决方案:How to setup OpenBlas on windows? #625 GGML 官网 https://github.com/ggerganov/ggml/issues/959 windows on arm 编译 llama.cpp 、ggml 后端启用自定义BLAS加速 …...
glb数据格式
glb数据格式 glb 文件格式只包含一个glb 文件,文件按照二进制存储,占空间小 浏览 浏览glb工具的很多,ccs,3D查看器等都可以,不安装软件的话用下面网页加载就可以,免费 glTF Viewer (donmccurdy.com) glb…...
手语识别系统源码分享
手语识别检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vision …...
Oracle 数据库部署与实施
文章目录 1. macOS 上部署 Oracle 数据库通过 Docker 在 macOS 上部署 2. Linux 上部署 Oracle 数据库直接在 Linux 上部署通过 Docker 在 Linux 上部署 3. Windows 上部署 Oracle 数据库4. 使用 Docker 部署 Oracle 数据库前提条件拉取 Oracle 数据库 Docker 镜像运行 Oracle …...
【Python】 ast.literal_eval 与 eval
一、背景 我在在编写管理后台的过程中,遇到一个小问题,是关于用户名的存储和解码。用户名以base64编码的形式存储在 MySQL 数据库中,并且还保留了b这样的形式,具体为什么要这样存我也不知道,可能是因为有些特殊字符无法直接存储。…...
Java 入门指南:JVM(Java虚拟机)垃圾回收机制 —— 新一代垃圾回收器 ZGC 收集器
文章目录 垃圾回收机制垃圾收集器垃圾收集器分类ZGC 收集器ZGC 的性能优势复制算法指针染色读屏障 ZGC 的工作过程Stop-The-World 暂停阶段并发阶段 垃圾回收机制 垃圾回收(Garbage Collection,GC),顾名思义就是释放垃圾占用的空…...
基于 K8S kubernetes 的常见日志收集方案
目录 1、日志对我们来说到底重不重要? 2、常见的日志收集方案 2.1 EFK 2.2 ELK Stack 2.3 ELKfilebeat 2.4 其他方案 2、elasticsearch组件介绍 3、filebeat组件介绍 3.1 filebeat和beat关系 3.2 filebeat是什么? 3.3 Filebeat工作原理 3.4 …...
Unity3D 小案例 像素贪吃蛇 02 蛇的觅食
Unity3D 小案例 像素贪吃蛇 第二期 蛇的觅食 像素贪吃蛇 食物生成 在场景中创建一个 2D 正方形,调整颜色,添加 Tag 并修改为 Food。 然后拖拽到 Assets 文件夹中变成预制体。 创建食物管理器 FoodManager.cs,添加单例,可以设置…...
【sgCreateCallAPIFunction】自定义小工具:敏捷开发→调用接口方法代码生成工具
<template><div :class"$options.name" class"sgDevTool"><sgHead /><div class"sg-container"><div class"sg-start"><div style"margin-bottom: 10px">调用接口方法定义列表</div…...
京东商品详情的 API 探秘与应用
在当今数字化的商业世界中,获取准确而详细的商品信息对于开发者、商家以及消费者都具有至关重要的意义。京东作为国内领先的电商平台之一,提供了丰富的商品资源和强大的 API 接口,让我们能够轻松获取京东商品的详情信息。本文将带你深入了解如…...
功能测试干了三年,快要废了。。。
8年前刚进入到IT行业,到现在学习软件测试的人越来越多,所以在这我想结合自己的一些看法给大家提一些建议。 最近聊到软件测试的行业内卷,越来越多的转行和大学生进入测试行业,导致软件测试已经饱和了,想要获得更好的待…...
数字化社交与营销突围:二维彩虹赋能电子名片与私域引流
在移动互联网深度渗透的今天,企业与个人面临的流量竞争日益激烈。传统的社交方式与营销手段正遭遇瓶颈:纸质名片易丢失、信息更新滞后;微信群二维码7天有效期导致流量流失;多平台推广链接分散,难以形成合力。面对这些痛…...
从“机器会思考”的执念说起,聊聊神经网络到底是个啥(下篇)
一、神经网络的类型:别被名字搞晕,核心就几种 现在叫“神经网络”的东西五花八门,但绝大多数都是从下面这几类衍生出去的。 1. 前馈神经网络(FNN)—— 最朴素的直筒子 数据从输入层进,经过若干隐藏层&am…...
保姆级教程:用Fine-Pruning防御深度学习后门攻击(附PyTorch代码)
深度学习模型安全防护实战:Fine-Pruning防御后门攻击全解析 在自动驾驶、人脸识别等关键AI应用场景中,模型安全性已成为产品落地的核心考量。近期研究表明,超过34%的开源预训练模型存在潜在后门风险,攻击者可通过精心设计的触发器…...
LiTmall:如何用Spring Boot + Vue + 微信小程序构建高效开源电商系统?
LiTmall:如何用Spring Boot Vue 微信小程序构建高效开源电商系统? 【免费下载链接】litemall linlinjava/litemall: LiTmall 是一个基于Spring Boot MyBatis的轻量级Java商城系统,适合中小型电商项目作为基础框架,便于快速搭建…...
CentOS 7 无线网卡“失踪”排查指南:从驱动到NetworkManager的全面诊断
1. 无线网卡消失的常见症状与初步检查 当你打开CentOS 7准备连接Wi-Fi时,突然发现系统提示"No Wi-Fi Adapter found",这种突如其来的网络"失踪"问题确实让人头疼。作为系统管理员,我遇到过太多次类似情况,有时…...
对于对话中的文本简化,OpenClaw 的压缩比和可读性如何平衡?
关于文本简化中压缩比与可读性的平衡,这其实是一个在工程实践中经常遇到的核心矛盾。OpenClaw 的处理方式,仔细推敲起来,背后反映的是一种偏向实用主义的权衡思路。 压缩比高,通常意味着文本被大幅度精简,只保留最核心…...
AudioSeal小白入门:无需代码,用90年代复古界面快速加密你的音频
AudioSeal小白入门:无需代码,用90年代复古界面快速加密你的音频 1. 什么是AudioSeal? AudioSeal是Meta公司开发的一款前沿音频水印技术,它能在不影响音质的前提下,将数字签名"隐形"嵌入到音频文件中。想象…...
如何让旧款Mac焕发新生:OpenCore Legacy Patcher终极指南
如何让旧款Mac焕发新生:OpenCore Legacy Patcher终极指南 【免费下载链接】OpenCore-Legacy-Patcher 体验与之前一样的macOS 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher 你是否有一台被苹果官方"遗忘"的旧款Mac&a…...
PyRadiomics环境配置全攻略:从依赖冲突到稳定运行的系统化解法
PyRadiomics环境配置全攻略:从依赖冲突到稳定运行的系统化解法 【免费下载链接】pyradiomics Open-source python package for the extraction of Radiomics features from 2D and 3D images and binary masks. Support: https://discourse.slicer.org/c/community/…...
突破Twitter数据限制:Rettiwt-API开源工具零成本数据获取指南
突破Twitter数据限制:Rettiwt-API开源工具零成本数据获取指南 【免费下载链接】Rettiwt-API An API for fetching data from Twitter for free! 项目地址: https://gitcode.com/gh_mirrors/re/Rettiwt-API 在社交媒体数据驱动决策的时代,Twitter作…...
