kitlau
kitlau

kitlau's blog

All Posts in 2023.7


如何 3 分钟搭建图片转文本工具

这篇博客详细介绍了如何在3分钟内搭建一个图片转文本工具。首先,作者选择了Laf,一个提供海外和大陆服务的平台,并创建了一个Laf应用。接着,作者创建了一个云函数,并设置了HuggingFace Access Token作为环境变量。在云函数中,作者使用JavaScript调用HuggingFace的API,实现了图片转文本的功能。作者还展示了如何调试云函数,并发布到Laf平台。最后,作者使用云函数返回的前端代码字符串,创建了一个简单的前端来实现图片转文本的功能。这个工具可以识别图片并将其转化为文字,如果你需要,也可以接入翻译接口,将识别结果翻译为中文。这篇文章详细而直观地展示了如何创建一个简单的图片转文本工具,你是否也想尝试一下呢?--GPT 4

AI

如何使用 Optional 模式解决 C# 中的烦人的空引用问题

这篇博客文章主要探讨了如何使用 Optional 模式解决 C# 中的空引用问题。首先,文章指出空引用异常是编程中常见的问题,常规的处理方法是在出错的代码位置添加判断,然后修复。然后,文章引入了 C# 中新引入的可空引用类型特性,但这个特性也带来了新的问题,如代码中充满了各种 null check 和 null guard。因此,文章提出了使用 Optional 模式来解决这个问题。Optional 模式提供了一种优雅的方式来处理可空值,避免了使用 null 值。文章还介绍了如何实现 Optional 模式,并提供了相关的代码和使用示例。最后,文章比较了 Nullable 和 Optional 模式,认为它们都是不错的解决空引用的方案,但选择哪种方案需要根据项目的大小和参与项目的成员等因素来决定。那么,你会选择哪种方式来解决空引用问题呢?--GPT 4

C#

Linq 和 lambda 的区别是什么?

本篇博客探讨了LINQ和lambda表达式的关系和区别。首先,LINQ(Language-Integrated Query)是一个库,包含一组可以使用lambda表达式的扩展方法,例如Where。文章通过代码示例详细解释了如何使用LINQ进行查询。其次,lambda表达式是一种更简单的构造匿名委托的方法,也被称为语法糖。它们经常在使用方法语法的LINQ中出现,这可能是人们常常把它们混淆的原因。文章再次通过代码示例解释了如何使用lambda表达式。最后,文章总结了lambda表达式实际上是一种比匿名方法更简单的委托创建方式,LINQ则可以通过表达式树把C#的查询语句转换成其他形式的查询语句,例如SQL语句。文章最后引用了一些相关的博客,供读者深入学习。那么,你是否清楚了LINQ和lambda表达式的区别呢?是否理解了它们各自的作用和用途呢?--GPT 4

C#

一幅漫画解释 .NET 垃圾收集(GC)原理

这篇博客主要讨论了.NET的垃圾收集(GC)原理。作者首先提到了许多普通dotnet开发者对dotnet的一些基础知识并不了解,这对他们的技术路线职业发展不利。在这种背景下,性能优化,尤其是从减少GC压力入手,成为了一个值得学习的点。作者随后翻译了一幅来源于Redgate的漫画,该漫画简单而直观地解释了dotnet GC的工作原理。同时,作者也提到了在dotnet 5中,GC新增了新的分代POH,但没有深入讨论。关于大对象堆(LOH)压缩问题,作者引用了@lorenzo_solano的解决方案,即设置`GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce`,但这个解决方案只在下一个GC周期有效。这篇博客为读者提供了一个关于.NET垃圾收集原理的基本科普,同时也引出了一些关于GC优化和内存管理的问题。你认为在什么情况下应该采用这种LOH压缩模式呢?这种模式的效果如何?这些问题可能需要你自己去寻找答案。--GPT 4

.NET

C# required:跟 string 的空引用异常说再见

这篇博客深入讨论了C#编程中的一个常见问题:空引用异常。首先,介绍了空引用异常的起源和常见情况,特别是在处理字符串数据时,由于字符串的默认值是null,这会导致很多误解。接着,详细解析了在C# 11之前如何解决这个问题,包括使用问号声明符号来声明可为null的字符串,以及使用null!来告诉编译器字符串绝对不会为null。然后,介绍了C# 11引入的required关键字,这个关键字可以直接声明字符串必须在对象初始化器里赋值,从而一步到位解决问题。最后,作者对当前的开发环境进行了吐槽,认为急功近利的开发环境会导致软件质量下降。这篇博客不仅提供了技术解决方案,也引发了对开发环境的思考:我们是否应该牺牲软件质量以追求快速开发?--GPT 4

C#

.NET 是如何编译的?如何阅读中间语言?

本篇博客详细解析了.NET中C#代码的编译过程,以及如何阅读中间语言(IL)。首先,通过dotnet build命令编译程序,编译器将C#高级代码编译成可执行文件中的中间语言代码。接着,解释了Common Intermediate Language(CIL,程序集层/汇编层)的概念,CLR可以将IL编译为Native code。博客还详细阐述了如何阅读IL,包括方法声明部分、方法内容部分的设置和执行等。最后,解释了从CIL到Native code的转换过程,这一步是在运行时由CLR调用JIT编译器完成的。通过本文,读者可以了解到.NET编译的全过程,以及如何阅读和理解IL。这对于理解.NET的工作原理,以及进行性能优化等方面都有很大的帮助。文章最后提出了一个问题:对比能达成相同结果的操作的性能和开销时,如何利用IL进行判断?--GPT 4

.NET

【译】.NET SDK 将会内置容器支持,不再需要 Dockerfile

.NET SDK即将内嵌容器支持,无需再使用Dockerfile。此功能允许开发者自定义生成的镜像的许多方面,包括选择Base镜像、镜像版本和名称等。此外,开发者可以在本地开发和CI管道中使用此功能,以更简单的方式创建和管理容器镜像。然而,此功能的初始预览版本还存在一些限制,例如暂不支持Windows镜像和非x64架构,也暂时无法推送到远程registries。但在dotnet 7的rc阶段,这些问题将得到解决。此功能的目标是简化容器镜像的构建过程,使之更加直观和易用。然而,目前还无法使用dotnet SDK执行RUN命令,这可能影响到一些需要在操作系统级别进行定制的应用。然而,随着这个功能的不断开发,这些问题有望得到解决。那么,这个功能是否能够替代Dockerfile并成为主流的容器构建工具呢?这个问题可能需要时间来回答。--GPT 4

.NET

还在背依赖注入的概念?不如自己写一个依赖注入框架

本篇博客以依赖注入(DI)框架为例,详细介绍了如何从零开始构建一个DI框架。首先,博客讲解了DI的基本概念,包括服务、服务描述符和服务提供者。接着,通过创建一个KServiceCollection类,实现了DI的基础功能。然后,通过使用KServiceCollection类创建一个KServiceProvider类,实现了服务的获取和注入。在此基础上,博客进一步讲解了如何通过创建单例和瞬态服务,实现不同生命周期的管理。最后,通过在控制台项目中创建新服务和重写Program.cs文件,进行了DI框架的测试。 此篇博客深入浅出地讲解了DI框架的构建过程,旨在帮助读者更好地理解DI的概念和应用。同时,博客也提出了一些有趣的问题,比如如何解决null值检查的问题,如何约束TImplement类型必须实现TService接口,如何实现Remove功能等,以引发读者的思考。而这些问题的解决,将是读者自己完成DI框架的关键步骤。 此外,博客也强调了编程学习的方式,批评了应试教育的学习方式,并指出这种方式对开发者创造力的扼杀。博客希望读者能够通过动手实践,真正理解和掌握编程知识。那么,你是否已经准备好,开始自己的DI框架构建之旅呢?--GPT 4

.NET DependencyInjection

异步的原理是什么?C# 如何基于状态机实现异步?

本篇博客详细解析了异步的原理以及C#如何基于状态机实现异步。首先,文章介绍了C#中的异步方法,包括其结构、状态机的工作方式以及如何通过IAsyncStateMachine接口实现异步。然后,博客详细讲解了状态机的MoveNext()方法,包括它的工作原理,如何在异步方法第一次调用时被调用,以及每次恢复执行时都被调用一次。文章还解释了在await表达式时,有两种可能,await的异步操作尚未完成,或者已经完成。最后,博客总结了MoveNext()方法的工作流程,并通过流程图形象地展示了异步方法的执行过程。那么,为什么“尚未启动”和“正在执行”状态用同一个值表示?这篇博客是否能帮助你理解C#异步的实现呢?--GPT 4

C#

什么是异步?异步就是多线程吗?异步就是 async、await 吗?

这篇博客主要探讨了异步编程的一些基本概念和用法,包括异步方法的调用、async/await关键字的作用以及异步方法的执行顺序等。通过一系列的示例,我们可以看到异步方法在被调用时就会立即开始执行,而await关键字则是用来等待异步方法执行完成并获取返回结果。在调用异步方法和await这个异步方法返回的Task之间,我们还可以去做其他事情,比如再运行一个与之前的异步方法无关的异步方法。此外,这篇博客还介绍了如何在不使用async修饰的情况下编写异步方法,以及如何使用Task.WhenAll()来同时等待多个Task完成。最后,作者指出虽然这篇文章只讲了异步编程的一些表象,但已经足够用来进行开发,如果要深入理解异步编程的原理,还需要进一步的学习和实践。那么,你是否已经理解了这些异步编程的基本概念和用法呢?你是否已经准备好放心大胆地使用异步编程了呢?--GPT 4

C#

EF Core 何时、为何使用 IsUnicode 方法

这篇博客主要讨论了EF Core中`IsUnicode()`方法的使用时机和原因。首先,作者通过实验发现,`IsUnicode()`对MariaDB没有什么用,对MSSQL Server则会改变C# string类型的属性在数据库中的数据类型。当不使用`IsUnicode()`或配置为`IsUnicode(true)`时,生成的数据库表中对应string字段的数据类型为`nvarchar`,而配置`IsUnicode(false)`时则为`varchar`。因此,作者建议,当我们确定一个string类型的属性是ASCII安全的时候,即这个属性的值只会包含数字、英文字母和英文符号时,可以为它配置`IsUnicode(false)`,这样它在数据库中就是`varchar`类型。但如果你不确定,最好还是保持默认。此外,作者还分享了他的一些经验,例如对于ASCII安全的字符串来说,`nvarchar`要比`varchar`多占1倍的存储空间,而且还要考虑性能的影响。在博客的最后,作者介绍了EF Core 6中引入的新特性:Unicode Attribute,并总结了软件开发中需要注意的一些问题。--GPT 4

C# EF Core

彻底理解 ASCII Unicode UTF-8 UTF-32 是什么以及区别与联系

本篇博客详细介绍了ASCII,Unicode,UTF-8和UTF-32的定义,起源以及它们之间的区别和联系。博客首先解释了ASCII的编码过程,然后介绍了由于ASCII无法表示除英文字符以外的其他文字和符号,Unicode标准的出现。Unicode包含100多种语言中的超过10万个独特字符。接着,博客详细描述了Unicode和ASCII的区别,以及如何将字素映射到编码点。接下来,博客讨论了UTF-8和UTF-32这两种编码策略,以及它们与ASCII的区别。UTF-32将每个编码点的值编码为4个字节,而UTF-8则将每个编码点编码为8-32位,即1到4个字节。最后,博客总结了在Unicode中,一个字素不等于一个编码点,也不等于一个字节,并且我们必须知道原始的编码规则才能将字节解码为字素。在阅读完整篇博客后,你是否能理解为什么在不同的编程语言中,相同的字符串在长度上可能会有所不同?你是否了解在何种情况下应使用不可感知Unicode的函数,可感知Unicode的函数和可感知字素的函数?--GPT 4


EF Core 动态构建表达式树简化 DDD 值对象的比较

本篇博客探讨了如何使用EF Core动态构建表达式树简化DDD值对象的比较。首先,文章讲述了如何在EF Core中使用值对象,以及遇到的问题。接着,文章提出了使用动态构建表达式树的查询作为解决方案,并详细解释了如何实现这个解决方案,包括创建一个名为`ValueObjectEqualHelper`的静态类,以及如何使用这个类中的`CheckEqual<T, TProperty>`静态方法。最后,博客展示了如何使用这个方法,并展示了生成的SQL脚本和输出结果。这个方法是否能够解决你在EF Core中使用值对象时遇到的问题呢?对于动态构建表达式树,你有什么其他的想法和建议吗?--GPT 4

.NET EF Core

EF Core 动态构建表达式树为所有实体设置软删除的查询过滤器

这篇博客文章介绍了如何在EF Core中动态构建表达式树,实现对所有实体设置软删除的查询过滤器。首先,文章通过一个简单的实体类和一个实体配置类来演示如何在EF Core中设置查询过滤器。然后,文章提出了一个问题:如果项目中有大量的实体,每个实体都进行一次查询过滤器的配置将会非常麻烦。为了解决这个问题,文章引入了动态构建表达式树的方法。通过动态构建表达式树,我们可以在应用程序启动时,遍历所有的实体类型,对有软删除标志的实体动态设置查询过滤器。文章还演示了如何在查询时忽略查询过滤器,以及如何简化动态构建表达式树的代码。最后,文章预告了下一篇博客的主题,将会介绍如何使用动态构建表达式树来简化和语义化领域驱动设计中值对象的比较。这篇博客对于那些在EF Core中使用查询过滤器,或者需要动态构建表达式树的开发人员来说,将会有很大的帮助。那么,你是否已经想象出如何在你的项目中应用这些方法了呢?--GPT 4

.NET EF Core

手把手构建 C# 表达式树

本篇博客详细解析了如何构建C#表达式树。首先,博客介绍了为何要构建表达式树,并以构建`p => p.Age > 18`这个lambda表达式为例,详细解释了构建过程。在构建过程中,首先创建了Person类,然后将表达式画成一个简单的表达式树,然后依次构建了树的各个节点,包括参数表达式、成员表达式、常量表达式、二元运算符表达式等。最后,将所有构建好的表达式组合成一个完整的lambda表达式。此外,博客还展示了如何使用这个构建好的表达式树,并解释了手动编译表达式的必要性。最后,博客预告了接下来会写两篇关于如何将表达式树应用在EF Core的文章,让读者对此产生了期待。那么,你是否已经理解了如何构建表达式树呢?你是否也对如何将其应用在EF Core中充满了好奇呢?--GPT 4

.NET

如何使用 CSharp 表达式树?

本篇博客详细介绍了如何使用 CSharp 表达式树,通过一个实际的例子展示了如何手动构建表达式树。博文首先解释了表达式树的概念,并通过 C# 中的语法树为读者提供了直观的理解。接着,博文对 .NET 中的 `Expression<TDelegate>` 类型进行了详细的解析,并通过代码示例展示了如何从 lambda 表达式生成 `Expression<TDelegate>` 类型的变量,以及如何将其编译成 `TDelegate` 类型的委托对象。然后,博文通过一个实际的例子,详细地介绍了如何手动构建表达式树,包括如何构建叶子节点和根节点,以及如何编译和调用表达式树。最后,博文提到了表达式树在简化值对象比较中的应用,并给出了相关的参考文档链接。那么,表达式树是否真的能够避免硬编码,从而使代码更易于维护呢?阅读全文,你将得到答案。--GPT 4

C#

【译】数据是如何存储在 SQL 数据库中

本篇博客主要讲述了数据在 SQL 数据库中的存储方式。首先,虽然表中的数据在逻辑上以行和列的格式存储,但在物理上,它以数据页的形式存储,数据页是 SQL Server 中数据存储的基本单位。其次,SQL Server 中的表数据实际上存储在一个类似树的结构中,这种树状结构被称为 B-Tree、index B-Tree 或 Clustered index structure。数据实际上存储在一系列数据页中,这些数据页的树形结构如下所示。在树底部的节点称为数据页或树的叶节点,正是这些叶节点包含我们的表数据。每个数据页的大小为 8KB,这意味着每个数据页中存储的行数实际上取决于每行的大小。位于树顶部的节点称为根节点,根节点和叶节点之间的节点称为 intermediate levels。根节点和中间层节点包含索引行,而叶节点包含实际的数据行。每个索引行包含一个键和一个指向 B 树中的中间层节点或叶节点中的数据行的指针。这个树状结构有一系列的指针,可以帮助数据库引擎快速找到数据。最后,文章简要介绍了 SQL Server 是如何通过 ID 找到一个数据行的。这篇博客对于理解 SQL 数据库的数据存储方式非常有帮助。你觉得 SQL Server 的这种数据存储方式有什么优点和缺点吗?--GPT 4

DB

【译】SQL 索引是如何工作的

本篇博客详细介绍了SQL索引的工作方式,包括聚集索引和非聚集索引的详细解释和实例演示。首先,博客解释了什么是聚集索引,如何通过ID查找数据行,并通过实例演示了如何创建一个包含一百万条数据的Employees表。然后,博客介绍了聚集索引查找和扫描的概念,以及它们的区别和使用场景。接着,博客解释了在SQL Server中创建非聚集索引的方法,以及非聚集和聚集索引的作用和使用方式。最后,博客通过实例演示了根据Name非聚集索引查询时的执行计划,以及Estimated Subtree Cost的概念。这篇博客对于理解和使用SQL索引非常有帮助,特别是对于需要处理大量数据的开发者。你是否了解过SQL索引的工作方式?你是否知道如何通过索引优化查询性能?你是否了解聚集索引和非聚集索引的区别和使用方式?阅读这篇博客,你将找到答案。--GPT 4

DB

如何在 CSharp 和 EF Core 中使用 UTC 时间

这篇博客主要讲述了如何在CSharp和EF Core中使用UTC时间,以及如何配合Mapster自动转换UTC时间到本地时间。首先,文章解释了什么是UTC时间,并详细描述了在C#中如何使用UTC时间,包括如何将所有DateTime和DateTime?类型且名称结尾为"Utc"的属性的Kind都设置为`Utc`。接着,文章介绍了如何配合EF Core使用UTC时间,通过在ApplicationDbContext.cs中进行设置,可以实现属性的批量转换。然后,文章探讨了如何便捷地使用UTC时间,将其转换为本地时间,包括三种常见的方式:给Product类再加`Created`和`Modified`两个属性,自定义一个Product类的DTO,或者使用AutoMapper或者Mapster等库来自动Mapping。最后,文章介绍了如何使用Mapster自动将UTC映射为本地时间。通过这些步骤,可以实现将ProductDto的Created和Modified都转换成美国的时间,避免了“在今天买到明天生产的牛奶”等问题。那么,你会选择哪种方式来使用UTC时间呢?--GPT 4

.NET