当前位置: 首页 > news >正文

C#记录类型与集合的深度解析:从默认实现到自定义比较器

记录与集合

这篇文章在某种程度上是我在使用选举网站中的记录和集合时遇到的一些摩擦点的汇总。

记录回顾

这可能最终成为本系列中最具普遍实用性的博客文章。尽管记录类型自C# 10以来就已存在,但我自己使用得并不多。(我期待使用它们已经超过十年了,但那是另一回事。)

决定使所有数据模型不可变后,使用记录类型(在我的情况下总是密封记录)在C#中实现这些模型几乎是理所当然的。只需使用与主构造函数相同的格式指定所需的属性,编译器就会为您完成一堆样板工作。

作为一个简单的例子,考虑以下记录声明:

public sealed record Candidate(int Id, string Name, int? MySocietyId, int? ParliamentId);

这将生成大致等效于以下代码:

public sealed class Candidate : IEquatable<Candidate>
{public int Id { get; }public string Name { get; }public int? MySocietyId { get; }public int? ParliamentId { get; }public Candidate(int id, string name, int? mySocietyId, int? parliamentId){Id = id;Name = name;MySocietyId = mySocietyId;ParliamentId = parliamentId;}public override bool Equals(object? obj) => obj is Candidate other && Equals(other);public override int GetHashCode(){// 实际代码还使用了EqualityContract,此处省略。int idHash = EqualityComparer<int>.Default.GetHashCode(Id);int hash = idHash * -1521134295;int nameHash = EqualityComparer<string>.Default.GetHashCode(Name);hash = (hash + nameHash) * -1521134295;int mySocietyIdHash = EqualityComparer<int?>.Default.GetHashCode(MySocietyId);hash = (hash + mySocietyIdHash) * -1521134295;int parliamentIdHash = EqualityComparer<int?>.Default.GetHashCode(ParliamentId);hash = (hash + parliamentIdHash) * -1521134295;return hash;}public bool Equals(Candidate? other){if (ReferenceEquals(this, other)){return true;}if (other is null){return false;}// 实际代码还使用了EqualityContract,此处省略。return EqualityComparer<int>.Default.Equals(Id, other.Id) &&EqualityComparer<string>.Default.Equals(Name, other.Name) &&EqualityComparer<int?>.Default.Equals(MySocietyId, other.MySocietyId) &&EqualityComparer<int?>.Default.Equals(ParliamentId, other.ParliamentId);}public static bool operator==(Candidate? left, Candidate? right) =>{if (ReferenceEquals(left, right)){return true;}if (left is null){return false;}return left.Equals(right);}public static bool operator!=(Candidate? left, Candidate? right) => !(left == right);public override string ToString() =>$"Candidate {{ Id = {Id}, Name = {Name}, MySocietyId = {MySocietyId}, ParliamentId = {ParliamentId} }}";public void Deconstruct(out int Id, out string Name, out int? MySocietyId, out int? ParliamentId) =>(Id, Name, MySocietyId, ParliamentId) = (this.Id, this.Name, this.MySocietyId, this.ParliamentId);
}

(使用主构造函数可以写得更简洁一些,但我保留了“老派”的C#风格以避免混淆。)

此外,编译器允许对记录使用with运算符,以基于现有实例和一些更新的属性创建新实例。例如:

var original = new Candidate(10, "Jon", 20, 30);
var updated = original with { Id = 40, Name = "Jonathan" };

这一切都很棒!除非它并不完全如此……

记录相等性

如上所示,记录的默认相等性实现为每个属性使用EqualityComparer<T>.Default。当属性类型的默认相等比较器是您想要的时,这很好——但情况并非总是如此。在我们的选举数据模型案例中,大多数类型都没问题——但ImmutableList<T>不是,而且我们经常使用它。

ImmutableList<T>本身不重写EqualsGetHashCode——因此它具有引用相等性语义。我真正想要的是为元素类型使用一个相等比较器,并说两个不可变列表如果具有相同的计数并且元素在成对考虑时相等,则它们是相等的。这很容易实现——以及一个合适的GetHashCode方法。它可以很容易地包装在一个实现IEqualityComparer<ImmutableList<T>>的类型中,尽管碰巧我还没有这样做。

不幸的是,C#中记录的工作方式,无法为给定属性指定要使用的相等比较器。如果您直接实现EqualsGetHashCode方法,这些方法将代替生成的版本使用(并且生成的Equals(object)代码仍将使用您实现的版本),但这意味着您必须为所有属性实现它。这反过来意味着,如果您在记录中添加新属性,您需要记住修改EqualsGetHashCode(我至少忘记过一次)——而如果您乐于使用默认生成的实现,添加属性是微不足道的。

我真正想要的是某种方式向编译器指示它应该使用指定的类型来获取属性的相等比较器(可以假定为无状态的)。例如,想象我们有这些类型:

// 想象这在框架中...
public interface IEqualityComparerProvider
{static abstract IEqualityComparer<T> GetEqualityComparer<T>();
}// 这个也是...
[AttributeUsage(AttributeTargets.Property)]
public sealed class EqualityComparerAttribute : Attribute
{public Type ProviderType { get; }public EqualityComparer(Type providerType){ProviderType = providerType;}
}

现在我可以这样实现接口:

public sealed class CollectionEqualityProvider : IEqualityComparerProvider
{public static IEqualityComparer<T> GetEqualityComparer<T>(){var type = typeof(T);if (!type.IsGenericType){throw new InvalidOperationException("Unsupported type");}var genericTypeDefinition = type.GetGenericTypeDefinition();if (genericTypeDefinition == typeof(ImmutableList<>)){// 实例化并返回适当的相等比较器}if (genericTypeDefinition == typeof(ImmutableDictionary<,>)){// 实例化并返回适当的相等比较器}// 等等...throw new InvalidOperationException("Unsupported type");}
}

不幸的是,注释将涉及进一步的反射——但这肯定是可行的。

然后我们可以这样声明一个记录:

public sealed record Ballot(Constituency Constituency,[IEqualityComparerProvider(typeof(CollectionEqualityProvider))] ImmutableList<Candidacy> Candidacies);

……我期望编译器生成如下代码:

public sealed class Ballot
{private static readonly IEqualityComparer<ImmutableList<Candidacy>> candidaciesComparer;// 跳过今天会生成的代码。public bool Equals(Candidate? other){if (ReferenceEquals(this, other)){return true;}if (other is null){return false;}return EqualityComparer<Constituency>.Default.Equals(Constituency, other.Constituency) &&candidaciesComparer.Equals(Candidacies, other.Candidacies);}public override int GetHashCode(){int constituencyHash = EqualityComparer<Constituency>.Default.GetHashCode(Constituency);int hash = constituencyHash * -1521134295;int candidaciesHash = candidaciesComparer.GetHashCode(Candidacies);hash = (hash + candidaciesHash) * -1521134295;return hash;}
}

我确信还有其他方法可以做到这一点。属性可以改为指定用于获取相等比较器的私有静态只读属性的名称,从而移除接口。或者GetEqualityComparer方法可以是非泛型的,带有一个Type参数(让编译器在调用后生成转换)。我几乎没有想过——但重要的是,对单个属性进行自定义相等比较的要求独立于所有其他属性。如果您已经有一个具有9个属性的记录,其中默认相等比较没问题,那么添加第10个需要更多自定义的属性很容易——而今天,您需要实现包括所有10个属性的EqualsGetHashCode

(对于属性的字符串格式化也可以这样说,但这还不是困扰我的领域。)

我遇到的下一个摩擦点也是关于相等性的,但方向不同。

引用相等性

如果您记得我关于数据模型的文章,在单个ElectionContext中,模型的引用相等性是我们所需要的。网站永远不需要通过指定来自不同上下文的Constituency来从一个上下文中获取(例如)2024年选举的选区结果。实际上,如果我 ever 发现代码试图这样做,那可能表明了一个错误:任何给定Web请求中的所有内容都应引用相同的ElectionContext

鉴于此,当我创建ImmutableDictionary<Constituency, Result>时,我想提供一个仅执行引用比较的IEqualityComparer<Constituency>。虽然这看起来很简单,但我发现当重新加载上下文时,它对构建视图模型所花费的时间产生了相当显著的影响。

我原本期望在框架中轻松找到一个引用相等比较器——但如果有一个,我错过了。

更新,2025-03-27T21:04Z,感谢Michael Damatov

正如Michael在评论中指出的,框架中有一个:System.Collections.Generic.ReferenceEqualityComparer——我记得当我第一次发现我需要一个时找到了它。但我愚蠢地 dismiss 了它。您看,它是非泛型的:

public sealed class ReferenceEqualityComparer :System.Collections.Generic.IEqualityComparer<object>,System.Collections.IEqualityComparer

当时我觉得这很奇怪且不太有用。为什么我只想要IEqualityComparer<object>而不是泛型的?

哦,Jon。愚蠢,愚蠢的Jon。

IEqualityComparer<T>在T中是逆变的——因此存在从IEqualityComparer<object>到任何类类型X的IEqualityComparer<X>的隐式引用转换。

我现在已经移除了我自己的泛型ReferenceEqualityComparer<T>类型……尽管这意味着我必须在之前通过比较器的类型推断类型的地方进行转换或显式指定一些类型参数。

更新结束

我现在已经养成了在数据模型中到处使用引用相等比较的习惯,这使得添加一些扩展方法是值得的——而这些方法可能不太适合添加到框架中(尽管它们可以很容易地通过NuGet包提供):

public static ImmutableDictionary<TKey, TValue> ToImmutableReferenceDictionary<TSource, TKey, TValue>(this IEnumerable<TSource> source,Func<TSource, TKey> keySelector,Func<TSource, TValue> elementSelector) where TKey : class =>source.ToImmutableDictionary(keySelector, elementSelector, ReferenceEqualityComparer<TKey>.Instance);public static ImmutableDictionary<TKey, TSource> ToImmutableReferenceDictionary<TSource, TKey>(this IEnumerable<TSource> source,Func<TSource, TKey> keySelector) where TKey : class =>source.ToImmutableDictionary(keySelector, ReferenceEqualityComparer<TKey>.Instance);public static ImmutableDictionary<TKey, TValue> ToImmutableReferenceDictionary<TKey, TValue>(this IDictionary<TKey, TValue> source) where TKey : class =>source.ToImmutableDictionary(ReferenceEqualityComparer<TKey>.Instance);public static ImmutableDictionary<TKey, TValue> ToImmutableReferenceDictionary<TKey, TValue, TSourceValue>(this IDictionary<TKey, TSourceValue> source, Func<KeyValuePair<TKey, TSourceValue>, TValue> elementSelector) where TKey : class =>source.ToImmutableDictionary(pair => pair.Key, elementSelector, ReferenceEqualityComparer<TKey>.Instance);

(我当然可以轻松添加类似的方法来构建查找。)请随意对名称提出异议——虽然它们只在选举仓库中,我不会太担心它们。

插曲

为什么不使引用相等性成为默认?

我可能在这里一石二鸟。如果我经常想要引用相等性,而“深度”相等性相对难以实现,为什么不直接提供使所有我的记录表现为引用相等比较的EqualsGetHashCode方法呢?

这当然是一个选项——但我确实依赖深度相等比较进行测试:例如,如果我两次加载相同的上下文,结果应该相等,否则就有问题。

此外,由于记录类型鼓励深度相等,感觉通过指定引用相等比较,我是在颠覆它们的自然行为。虽然我不期望其他任何人会看到这段代码,但我不喜欢编写会混淆那些基于大多数代码工作方式带有期望的读者的代码。

插曲结束

说到常用比较器的扩展方法……

序数字符串比较

字符串比较让我紧张。我绝对不是国际化专家,但我知道 enough 知道它很复杂。

我也知道 enough 可以合理地确信默认字符串比较对于EqualsGetHashCode是序数的,但对于CompareTo是文化敏感的。正如我所说,我对此相当自信——但我总是发现很难验证,因此鉴于我几乎总是想使用序数比较,我喜欢明确。以前我指定了StringComparer.Ordinal(或偶尔StringComparer.OrdinalIgnoreCase)但是——就像上面的引用相等比较器一样——如果您经常使用它,这会变得烦人。

因此,我创建了另一组扩展方法,只是为了明确表示我想使用序数字符串比较——即使(在相等性的情况下)那已经是默认的。

我不会用完整的方法来烦您,但我有:

  • OrderByOrdinal
  • OrderByOrdinalDescending
  • ThenByOrdinal
  • ThenByOrdinalDescending
  • ToImmutableOrdinalDictionary(4个重载,类似于上面的ToImmutableReferenceDictionary
  • ToOrdinalDictionary(又是4个重载)
  • ToOrdinalLookup(2个重载)

(我实际上不常用ToOrdinalLookup,但实现所有这些感觉是明智的。)

这些在框架中会有用吗?可能。我明白为什么它们不在那里——字符串“只是另一种类型”真的……但我敢打赌,LINQ的使用中有很高比例最终以某种形式将字符串作为键。也许我应该建议将其加入MoreLINQ——尽管在15年前启动该项目后,我已经十多年没有为其做出贡献了……

Visual Studio中主构造函数和记录“调用层次结构”的小问题

我一直在Visual Studio中使用“调用层次结构”。将光标放在成员上,然后按Ctrl-K, Ctrl-T,您可以看到调用该成员的所有内容,以及调用调用者的内容,等等。

对于主构造函数和记录参数,“查找引用”有效(Ctrl-K, Ctrl-R),但“调用层次结构”无效。我可以接受“调用层次结构”对主构造函数参数无效,但由于记录参数成为属性,我期望看到它们的调用层次结构,就像我可以看到任何其他属性一样。

但更令人沮丧的是无法看到“调用构造函数”的调用层次结构。鉴于类/记录的声明在某种程度上也充当构造函数的声明,我以为将光标放在类/记录声明上(在名称中)会有效。并不是说它是模糊的——Visual Studio只是抱怨“光标必须在成员名称上”。您可以通过在解决方案资源管理器中展开源文件条目来访问调用,但仅在这种情况下必须这样做很奇怪。

功能请求(针对C#语言、.NET和Visual Studio)

总之,我喜欢记录,也喜欢不可变集合——但通过引入以下内容可以减少一些摩擦:

  • 某种方式(基于每个属性)控制生成代码中使用哪个相等比较器
  • 不可变集合的相等比较器,能够指定要使用的元素比较
  • 执行引用比较的IEqualityComparer<T>实现
  • 显示主构造函数和记录构造函数调用的“调用层次结构”

结论

我在记录和集合中发现的一些小问题至少在一定程度上特定于我的选举网站,尽管我强烈怀疑我不是唯一一个在记录中拥有不可变集合并希望在相等比较中使用它们的开发人员。

总体而言,记录在网站中到目前为止表现良好,我肯定很高兴它们可用,即使仍有改进的可能。同样,能够自然获得不可变集合也很棒——但一些在执行比较方面的帮助将是受欢迎的。
更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)
公众号二维码

相关文章:

C#记录类型与集合的深度解析:从默认实现到自定义比较器

本文深入探讨C#记录类型与不可变集合在实际应用中的挑战,包括默认相等性实现的局限性、自定义比较器的需求、引用相等性的应用场景,以及Visual Studio工具支持方面的不足,并提出了具体的语言和工具改进建议。记录与集合 这篇文章在某种程度上是我在使用选举网站中的记录和集…...

安徽京准:NTP时间服务器助力网络数据安全稳定

安徽京准:NTP时间服务器助力网络数据安全稳定 安徽京准:NTP时间服务器助力网络数据安全稳定安徽京准:NTP时间服务器助力网络数据安全稳定 京准电钟官微——ahjzsz NTP时间服务器确实是保障网络数据安全与稳定的重要基石。它通过提供高精度、高可靠、高安全的时间同步服务,为…...

UOS统信服务器操作系统V20(1070)安装mysql5.7.42

环境:OS:UOS Server 20 统信服务器操作系统V20(1070)mysql:5.7.42 操作系统下载https://www.chinauos.com/resource/download-server查看系统glibc版本[root@localhost yum.repos.d]# ldd --versionldd (GNU libc) 2.28Copyright (C) 2018 Free Software Foundation, Inc.This …...

响应式问题

今天遇到一个问题,组件已经设计为响应式,但是在移动端字体太小,多次调试无果,最终发现原因就在于我在main.js入口文件中引用了如下函数/*** 设置根元素的字体大小,以实现页面的自适应布局。* @param {number} bs - 基准字体大小,默认值为 16* @param {number} width - 设…...

Python 函数缓存

作用缓存不同参数组合的计算结果,命中缓存可以直接返回结果。使用示例import time from functools import lru_cache@lru_cache(maxsize=128) # 指定128个不同参数组合的调用结果,lru策略,设置为None表示无上限 def test(step: int, turns: int) -> int:total = 0for _ i…...

乐蜂直播购物商城小程序介绍

一、概述总结 乐蜂直播购物商城小程序系统,是一款依托微擎系统交付的直播电商解决方案。微擎系统是基于 PHP 开发的开源应用生态系统,可快速搭建微信公众号、小程序等应用,同时支持 Web 系统开发与部署,乐蜂直播购物商城小程序系统借助这一基础,实现了微信小程序内直播带货…...

基于C#实现基恩士PLC通信

一、通信协议选择 基恩士PLC支持多种通信协议,推荐优先采用以下两种方案:TCP/IP Socket通信(通用性强,适用于以太网接口设备) Modbus TCP协议(标准工业协议,兼容性强)二、Socket通信实现(基于TCP/IP) 1. 基础通信类设计 using System.Net.Sockets; using System.Text…...

VIPSHOP 门店会员营销管家:助力实体商家数字化运营

一、概述总结 VIPSHOP 门店会员营销管家是针对实体商家在微信生态开展会员营销与销售的工具,依托微擎系统实现交付与更新。其核心目标是帮助商家解决 “获客难、留客难、老客激活难” 的痛点,通过构建会员等级体系、整合多元营销功能,将线下流量转化为线上私域资产,形成 “…...

Rhino 8.10 中文版下载安装步骤(附详细图文说明)

软件介绍 犀牛Rhino 8.10是一款功能强大的三维建模软件,它是基于NURBS(非均匀有理B样条)技术的建模工具,广泛应用于工业设计、建筑设计、珠宝设计、三维动画等多个领域。以下是犀牛Rhino 8.10的简介: 1. 功能特点: – NURBS建模: Rhino 8.10以NURBS建模功能为核心,能够…...

深入解析:第十四届蓝桥杯青少组C++选拔赛[2022.12.18]第二部分编程题(2、字符翻转)

深入解析:第十四届蓝桥杯青少组C++选拔赛[2022.12.18]第二部分编程题(2、字符翻转)pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", …...

指令的执行过程

指令周期 cpu从主存中每取出一条指令所需要的全部时间 开始->取指令->对指令译码->执行指令->取下一条指令pc+1 指令周期常常使用若干个机器周期来表示,机器周期又叫cpu周期 一个机器周期包含若干个时钟周期(也被称作节拍,t周期,cpu时钟周期 也是cpu操作的基本…...

ALINX 助力希腊 SpaceDot AcubeSAT 卫星任务,2026 将入太空

ALINX 助力希腊 SpaceDot AcubeSAT 卫星任务,2026 将入太空pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New",…...

Ubuntu 安装JDK8

# 卸载当前的 JRE sudo apt remove openjdk-8-jre-headless# 安装完整的 JDK sudo apt install openjdk-8-jdk# 验证安装 java -version javac -version jps -l...

负载均衡层详解part 4

# keepaviled高可用 ## 一、keepaviled简介 负载均衡由七层负载均衡衍生出多级负载均衡,多出来四层负载均衡,再往前分就是DNS轮询,各种简单的、复杂的场景搭配用就可以了,有一个问题始终没有解决,整个集群架构中有的点是有单点故障问题的,怎么解决这个单点故障问题呢?就…...

重磅!中国科学引文数据库(CSCD)收录期刊(2025-2026)目录公布!共收录1464种期刊!

经过中国科学引文数据库(Chinese Science Citation Database,简称CSCD)定量遴选、专家定性评估, 2025-2026年度中国科学引文数据库收录来源期刊1464种,其中英文版期刊418种,中文版期刊1046种。 中国科学引文数据库来源期刊列表(2025-2026年度),因为篇幅较长,感兴趣(C…...

Flash Attenion算法原理

Flash Attenion算法原理 1.1 Flash Attention Step-by-Step1.2 Softmax \( \text{softmax}(x_i) = \frac{e^{x_i}}{\sum_{k=1}^{N} e^{x_k}} \)import torch A = torch.randn(2, 6) A_exp = torch.exp(A) A_sum = torch.sum(A_exp, dim=1).unsqueeze(1) P = A_exp / A_sum #广…...

电流探头消磁失败的原因与解决策略

在电子测量领域,电流探头的精准度是确保测试数据可靠性的关键因素,而消磁操作则是维持其测量精度的重要环节。消磁的主要目的是消除探头内部磁芯的剩磁,防止其对后续测量造成干扰。然而,在实际操作过程中,电流探头的消磁失败现象时有发生,这不仅会降低测量结果的准确性,…...

【算法】双指针(四)-盛最多水的容器 - 实践

【算法】双指针(四)-盛最多水的容器 - 实践pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !impo…...

程序设计小学期小计

小学期游记程序设计小学期小计 昨天奋斗到晚 12 点,算是完成了小游戏的所有功能,小游戏的主体流程算是全部完成了。写一篇小计记录一下。 截至目前,这个项目已经有了 \(233\) 次提交,若干次的合并,构筑起了这个小游戏。 过程 我们组当初提出制作 3D 的网页游戏,这是往届前…...

3dma渲染噪点成因排查及优化方案 - 详解

3dma渲染噪点成因排查及优化方案 - 详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !importa…...

hadoop配置日志聚集

日志聚集概念:应用运行完成以后,将程序运行日志信息上传到HDFS系统上。日志聚集功能好处:可以方便地查看到程序运行详情,方便开发调试。 注意:开启日志聚集功能,需要重新启动NodeManager 、ResourceManager和HistoryServer。[hadoop@hadoop101(192.168.0.101) /opt/modul…...

vxe-tree-select 树形下拉框当使用懒加载数据时如何回显

vxe-tree-select 树形下拉框当使用懒加载数据时如何回显 当使用懒加载或者当某个选项被删除时,显示自定义回显;比如使用懒加载树列表,由于数据未被加载,这时候已选的数据就不能被回显,导致显示了 value值,而不是 label。 还有一种场景就是组织架构人员选择,当选择某个人…...

GPT PMBR 大小不符解决方法

GPT PMBR 大小不符解决方法服务器输入fdisk -l 报GPT PMBR 大小不符(104857599 != 209715199),将用写入予以更正。The backup GPT table is not on the end of the device. This problem will be corrected by write. 通过采用parted -l就行修复,如下图 修复后,fdisk -…...

CodeFormer一款既能图像修复、还能视频增强去码的AI软件(下载介绍)

CodeFormer是一款强大的人工智能工具,主要用于图像和视频的修复和增强。它基于深度学习技术,特别是人脸复原模型,可以轻松修复和增强面部图像,提升照片和视频的质量和视觉效果工作原理 1、通过自动编码器实现人脸的变换,包括色彩化、清晰化、去马赛克修复等功能 2、采用了…...

PCB的导线电阻阻抗批量自动计算EXCEL表格工具 公式

https://wwqx.lanzoul.com/iv1Fg36h5xwh 密码:hcko...

微信协议开发个微API

微信协议开发个微API常见开发功能: 好友管理: 维护好友列表:包括添加、删除、修改好友信息。 分组管理:创建、编辑、删除标签,以便更好地组织好友。 消息管理: 信息发送:支持发送各种类型的消息,包括文本、图片、名片、动图表情、小程序、文件、视频和URL链接及防撤回等…...

Milvus Lite

Milvus (标准版):就像一个部署在专业机房、由多台服务器组成的大型数据中心。它性能强大、稳定可靠、支持高并发,是生产环境的不二之选。部署它,通常需要使用Docker或在Linux服务器上进行。Milvus Lite (轻量版):就像一台功能强大、开箱即用的个人开发笔记本。它把数据中心…...

如何解除 pip install 安装报错 ModuleNotFoundError: No module named ‘win32api’ 问题

如何解除 pip install 安装报错 ModuleNotFoundError: No module named ‘win32api’ 问题pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco&quo…...

hbase学习一

什么是HBase? HBase是一个基于HDFS的、分布式、可扩展、面向列的NoSQL数据库。它起源于Google的BigTable论文,是Apache Hadoop生态系统的重要组成部分,专门用于处理海量数据的随机、实时读写访问。为什么需要HBase? Hadoop HDFS适合批处理,但无法进行随机读写。MapReduce适…...

【光照】[漫反射diffuse]以UnityURP为例

这篇文章介绍了Unity URP渲染管线中漫反射光照的实现原理和流程。主要内容包括:1. 漫反射遵循兰伯特定律,通过法线准备、光源方向计算、点积运算等步骤实现;2. URP的具体实现细节,如法线处理、光源计算和多光源支持;3. 关键代码示例,包括漫反射计算和完整光照流程;4. 快…...

OI线下比赛注意事项

这篇写挺好 https://www.cnblogs.com/dengstar/p/17069134.html...

n8n实践-使用n8n搭建一个定时发送天气预报邮件的工作流

前言传统的定时任务,一般是使用linux cron定时运行某个位置的某个脚本。需要准备各种运行环境; 脚本比较分散,管理起来相对麻烦; 需要有一定的代码能力,比如常见的shell、python等等; 不方便接入ai, 更换ai也比较麻烦。工作流的好处是:把定时任务、触发任务等统一管理; …...

Cython-编程学习指南第二版-全-

Cython 编程学习指南第二版(全)原文:zh.annas-archive.org/md5/0bc691743f26fcdcabcb6840b706a834 译者:飞龙 协议:CC BY-NC-SA 4.0前言 Cython 是一个工具,它使得编写 Python 的原生扩展变得和编写 Python 代码一样简单。对于那些不知道的人来说,你可以将 Python 模块实…...

印度尼西亚股票数据API对接实现

环境准备 首先安装必要的依赖包: pip install requests websocket-client pandas numpy基础配置 import requests import json import websocket import threading import time from datetime import datetime# API配置 API_KEY = "YOUR_API_KEY" # 替换为您的实际…...

OpenBMB 发布无分词器 TTS VoxCPM;儿童口语硬件 Dex 融资 480 万美元:拍摄真实物体,对话学习外语丨日报

开发者朋友们大家好:这里是 「RTE 开发者日报」,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的技术」、「有亮点的产品」、「有思考的文章」、「有态度的观点」、「有看点的活动」,但内容仅代表编辑的个人观点…...

一天一款实用的AI工具,第1期,AI标题生成工具

本期介绍的是一款专业的标题生成工具,它能帮你产出高质量标题,让点击率提升,让内容被看见。现实问题 在内容创作的世界里,有句话特别扎心: 好的标题=成功的一半。 很多创作者都遇到过这样的困境: 花了一下午写好一篇文章,结果标题平平无奇,点击量惨淡。 明明内容不错,…...

重组蛋白表达避坑指南

重组蛋白表达避坑指南重组蛋白表达是分子生物学、生物技术以及生物医学研究中非常基础却经常“出问题”的环节。一个合适的蛋白表达方案,不仅要能产生足够的产量,还要确保蛋白正确折叠、具有功能、具有良好的纯度与稳定性。一、选择表达系统与宿主:第一个关键决策常见问题不…...

易被忽略的vim中视图模式

常见的都是vim三种模式,但视图模式也不可忽略,主要进行批量操作在 Vim 中,可视模式(Visual Mode)是一种强大的文本选择和编辑模式,允许你高亮选中一段文本,然后对其进行操作(如复制、删除、替换、注释等)。 一:三种可视模式1.字符可视模式 用途: 精确选择字符或单词…...

电商核心业务 - 指南

电商核心业务 - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important; font-size: 14p…...

一言

一些日常的感想,为了节约时间,为了不暴露太多东西,为了不挑起矛盾,内容会很简洁,在合适的时候公布详情。9.17 说好的向阳而生呢?冷静啊,兄弟。 9.18 你们不相信我,我必将证明我,夺回属于我的荣耀。...

ai

https://qsqs.life/login?redirect=/system/dashboard本文来自博客园,作者:zjxgdq,转载请注明原文链接:https://www.cnblogs.com/zjxzhj/p/19098509...

LlamaIndex 项目深度技术分析 - 详解

LlamaIndex 项目深度技术分析 - 详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important;…...

深入解析:css消除图片下的白边

深入解析:css消除图片下的白边pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", monospace !important; font…...

linux增加网卡ip地址

linux增加网卡ip地址example ip addr add 192.168.5.124/24 dev eth0 label eth0:5 ifconfig eth0:5 up ip addr del 192.168.1.100/24 dev eth0 example ip addr add 192.168.10.199/24 dev eth0 label eth0:10 route add default gw 192.168.10.254reference: https://blog.c…...

Python 包与环境管理简史:从混乱到优雅

自动包管理工具的先驱:easy_install 在一切规范化工具出现之前,Python 的包管理是相当原始的。开发者们需要把第三方库的源码下载下来,手动放到项目目录里。 为了解决自动安装包的问题,easy_install 应运而生。 2004年:easy_install——从 0 到 1 的突破 easy_install 是 …...

qoj853 Flat Organization

SOLUTION FROM WUMIN4 题意 给出一个 \(n\) 个点的带权竞赛图(定向完全图),你可以进行任意次操作,每次操作反转一条边,代价为边权,求使得图强连通的最小代价和与方案,或输出无解。 \(n\le 2000\)。 思路 我们先考虑算出这张图的所有 SCC 并进行缩点,容易发现缩点后图是…...

shell命令中循环执行操作的命令

shell命令中循环执行操作的命令reference: for i in $(seq 1 10000); do echo "Iteration $i" && echo "Iteration $i"; done for i in $(seq 1 10000); do cat /sys/class/net/eth0/carrier && sleep 1; done for i in $(seq 1 999999); …...

2025年9月中国数据库排行榜:达梦挺进榜眼位,崖山首入前十强

9月墨天轮排行榜解读已出炉!本月前十变动较大,老将突围、新秀崛起,达梦凭借强劲势头跃升至第二位、TiDB排名上升、崖山首次闯入前十,此外还有一些产品表现亮眼!本月墨天轮社区的中国数据库排行榜再起波澜。达梦凭借强劲势头跃升至第二位,崖山则首次闯入前十,既展现了“老…...

基于QEMU模拟器搭建Builtroot下的QT开发环境

基于QEMU模拟器搭建Builtroot下的QT开发环境https://www.cnblogs.com/arnoldlu/p/17250728.html...

vlan

vlanhttps://zhuanlan.zhihu.com/p/385949949...