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

类型安全与代码复用的C# 泛型

一、引言:泛型 ——C# 编程的神奇钥匙

在 C# 编程的广袤天地里,泛型宛如一把神奇钥匙,能够开启高效、灵活且安全的代码之门🚪。

想象一下,你是一位经验丰富的建筑师,要建造各种各样的房子🏠。如果没有泛型,就好比你每建造一种风格的房子,都得重新设计一套全新的建造方案,从打地基到盖屋顶,事无巨细都得重来一遍,这无疑是个巨大的工程,不仅耗费时间精力,还容易出错。

而有了泛型,情况就大不一样了!它就像是一个万能的建筑蓝图模板📜,你只需要在这个模板上,根据不同房子的需求(如住宅、别墅、写字楼等),填入具体的参数(比如房间数量、面积大小、功能布局等),就能快速搭建出各种类型的房子。

在 C# 中,泛型让我们可以定义出通用的代码结构,无论是处理整数、字符串,还是自定义的复杂数据类型,都能像使用定制化工具一样得心应手,极大地提升了编程效率与代码质量。现在,就让我们一同深入探索 C# 泛型的奇妙世界吧!

二、初窥泛型:概念与魔法初现

究竟什么是泛型呢🧐?在 C# 中,泛型是一种极为强大的机制,它允许我们在定义方法、属性、索引器、委托、事件乃至类型时,先不着急确定具体的数据类型,而是使用类型参数来作为占位符。就好比我们在打造一个万能模具,这个模具在一开始并不限定只能制作某一种特定形状的物品,而是预留了一些可调整的参数,等到真正使用时,再依据需求填入具体的形状信息,从而制作出各种各样的成品。

比如说,我们有一个传统的非泛型方法,用于打印传入参数的值:

public static void PrintIntValue(int number)
{Console.WriteLine($"{number.GetType()}_Value:{number}");
}
public static void PrintStringValue(string str)
{Console.WriteLine($"{str.GetType()}_Value:{str}");
}

可以看到,如果要处理不同的数据类型,如整数、字符串等,就得分别定义不同的方法,代码显得冗长且重复。一旦需要新增一种数据类型,还得再写一个对应的新方法,这无疑给开发和维护带来了极大的不便。

而使用泛型方法,情况就截然不同了:

public static void PrintValue<T>(T parameter)
{Console.WriteLine($"{parameter.GetType()}_Value:{parameter}");
}

在这个泛型方法 PrintValue 中, 就是类型参数,它就像是一个万能插槽,能够接纳各种不同类型的数据。当我们调用这个方法时,编译器会根据传入的实际参数类型,自动推断出 T 所代表的具体类型,从而实现对不同类型数据的通用处理。例如:

PrintValue(123);  // 处理整数
PrintValue("Hello, World!");  // 处理字符串

如此一来,代码变得简洁明了,复用性大大增强,无论后续需要处理多少种新的数据类型,都无需再重复编写类似的方法,极大地提高了开发效率。这,就是泛型的初步魅力展现,是不是已经让你感受到它的神奇之处了呢😃?

三、类型安全:守护代码的坚固盾牌

(一)编译时的安检员

泛型最为突出的优势之一,便是其强大的类型安全保障机制。在编译阶段,编译器就如同一位严谨细致的安检员,会对泛型代码中的类型进行严格审查👮。

当我们定义了一个泛型类 GenericClass,并尝试使用 GenericClass 实例化它时,编译器会确保后续所有操作都与 string 类型相符。若不小心传入了一个整数,编译器立马就会发出 “警报”,提示类型不匹配错误,阻止代码进入运行时,避免了潜在的类型错误隐患。

而在非泛型的场景下,就好比一座没有门禁的城池,各种类型的数据可以随意进出。例如,使用传统的 ArrayList 类(非泛型),它可以存储任意类型的对象,因为它内部将所有元素都当作 Object 类型来处理。这看似方便,实则隐藏巨大风险,一旦进行类型转换操作,就可能在运行时引发 InvalidCastException 异常,导致程序崩溃,就像城池突然陷入混乱一般,后果不堪设想。

所以,泛型的类型安全特性就像是给代码加上了一道坚固的防护盾🛡,提前将错误拦截在编译阶段,让程序的稳定性得到极大保障,为后续的顺利运行奠定坚实基础。

(二)案例警示:类型错误的 “灾难现场”

为了更直观地感受泛型在类型安全方面的巨大优势,我们来看一个具体案例。

假设我们有一个非泛型的方法,用于计算一组数字的平均值:

public static double CalculateAverage(ArrayList numbers)
{double sum = 0;foreach (object number in numbers){sum += (double)number;  // 此处存在潜在类型转换问题}return sum / numbers.Count;
}

在调用这个方法时:

ArrayList numberList = new ArrayList();
numberList.Add(10);
numberList.Add(20);
numberList.Add("30");  // 不小心混入了一个字符串
double average = CalculateAverage(numberList);

当代码运行到 sum += (double)number; 这一行时,由于 numberList 中混入了字符串 “30”,在强制转换为 double 类型时,就会抛出 InvalidCastException 异常,程序瞬间崩溃,后续流程无法继续执行,就像一辆高速行驶的汽车突然爆胎,陷入失控状态。

而如果使用泛型来实现同样的功能:

public static double CalculateAverage<T>(List<T> numbers) where T : struct, IConvertible
{double sum = 0;foreach (T number in numbers){sum += number.ToDouble(null);}return sum / numbers.Count;
}

调用时:

List<int> numberList = new List<int>();
numberList.Add(10);
numberList.Add(20);
numberList.Add(30); 
double average = CalculateAverage(numberList);

由于泛型方法 CalculateAverage 通过 where T : struct, IConvertible 约束了类型参数 T 必须是可转换为数值类型的结构体,编译器在编译阶段就能发现类型不匹配的问题,比如若尝试传入包含字符串的列表,编译就无法通过,从源头上避免了运行时错误的发生,确保程序稳定运行,就像给汽车配备了优质的轮胎和智能的胎压监测系统,提前预警并排除隐患,一路畅行无阻。

四、代码复用:编程路上的万能钥匙

(一)一处编写,多处适用

泛型最为人称道的特性之一,便是其卓越的代码复用能力。它宛如一把万能钥匙,能够打开适配多种数据类型的代码之门🚪。

在实际编程过程中,我们常常会遇到这样的场景:需要对不同的数据类型执行相似的操作。例如,我们可能需要编写方法来处理整数数组、字符串数组以及自定义数据类型的数组,若不使用泛型,就不得不针对每种数据类型分别创建对应的方法,这无疑会导致代码量剧增,且充斥着大量重复逻辑,后期的维护成本也会直线飙升。

而有了泛型,情况则截然不同。我们可以定义一个泛型方法,使其能够处理各种类型的数组。就像下面这个示例:

public static void PrintArray<T>(T[] array)
{foreach (T item in array){Console.WriteLine(item);}
}

在这个方法中, 作为类型参数,让 PrintArray 具备了处理任意类型数组的能力。无论是 int[]、string[] 还是其他自定义类型的数组,都可以统一交给这个方法来处理:

int[] intArray = { 1, 2, 3, 4, 5 };
string[] stringArray = { "Hello", "World", "!" };
PrintArray(intArray);
PrintArray(stringArray);

如此一来,代码变得简洁高效,我们只需编写一次 PrintArray 方法,就能在不同的数据类型场景中重复使用,极大地提升了开发效率,减少了代码冗余,让我们的编程之路更加顺畅🛣。

(二)泛型类与方法:复用的两大法宝

泛型类和泛型方法就像是代码复用的两大法宝,各自发挥着独特的威力。

先来说说泛型类,它就像是一个万能的工具箱🧰,可以根据不同的需求盛装各种类型的工具(数据)。以一个简单的自定义集合类为例,假设我们要创建一个能够存储不同类型元素的列表:

public class MyList<T>
{private T[] items;private int count;public MyList(){items = new T[10];  // 初始容量为 10,可按需调整count = 0;}public void Add(T item){if (count < items.Length){items[count++] = item;}}public T GetItem(int index){if (index >= 0 && index < count){return items[index];}return default(T);  // 返回类型 T 的默认值}
}

通过 MyList,我们可以轻松创建存储不同类型数据的列表实例,如 MyList 用于存储整数,MyList 用于存储字符串,无需为每种数据类型单独编写一个列表类,复用性极强。

再看看泛型方法,它更像是一个万能的工具,能够灵活处理各种类型的数据。比如,我们有一个需求是对两个不同类型的变量进行交换操作:

public static void Swap<T>(ref T a, ref T b)
{T temp = a;a = b;b = temp;
}

这个 Swap 方法可以处理任意类型的变量交换,只要传入的两个变量类型相同即可。无论是交换整数、字符串,还是其他复杂对象(前提是对象所属的类支持赋值操作),它都能完美胜任,真正实现了 “一处编写,处处可用”,为代码复用提供了强有力的支持,让我们在编程的海洋中如鱼得水🐟。

五、实战演练:泛型在项目中的高光时刻

纸上得来终觉浅,让我们走进实际项目的 “战场”,看看泛型是如何大显身手的💪。

在一个数据处理项目中,我们需要对来自不同数据源(如数据库、文件、网络接口等)的数据进行清洗、转换与分析。这些数据类型五花八门,有整数、字符串、日期,还有复杂的自定义数据结构。

若未使用泛型,代码可能会陷入 “类型泥沼”。以数据清洗为例,针对整数类型,我们或许会写一个方法来去除异常值:

public static List<int> CleanIntegerData(List<int> data)
{List<int> cleanData = new List<int>();foreach (int value in data){if (value > 0 && value < 100)  // 简单的异常值判断,仅作示例{cleanData.Add(value);}}return cleanData;
}

而对于字符串类型,又得另起炉灶:

public static List<string> CleanStringData(List<string> data)
{List<string> cleanData = new List<string>();foreach (string value in data){if (!string.IsNullOrEmpty(value) && value.Length < 50)  // 简单的字符串清理条件,仅作示例{cleanData.Add(value);}}return cleanData;
}

随着数据类型的增多,代码量呈指数级增长,维护成本飙升,仿佛陷入了一团乱麻。

但有了泛型,我们就能打造一个 “万能清洗机”:

public static List<T> CleanData<T>(List<T> data, Func<T, bool> validationRule)
{List<T> cleanData = new List<T>();foreach (T value in data){if (validationRule(value)){cleanData.Add(value);}}return cleanData;
}

这里,通过泛型方法 CleanData,并引入一个委托类型的参数 validationRule 来定义不同类型数据的清理规则。使用时,无论是整数、字符串还是其他类型,都能轻松应对:

// 清洗整数数据
List<int> integerData = new List<int> { 10, -5, 50, 120 };
List<int> cleanIntegerData = CleanData(integerData, value => value > 0 && value < 100);// 清洗字符串数据
List<string> stringData = new List<string> { "", "Hello", "VeryLongString", "World" };
List<string> cleanStringData = CleanData(stringData, value =>!string.IsNullOrEmpty(value) && value.Length < 50);

如此一来,代码简洁明了,复用性极高,无论后续遇到多少种新的数据类型,都能从容应对,极大地提升了开发效率,让数据处理流程如丝般顺滑🛤。

再看业务逻辑层,假设我们正在开发一个电商系统,其中有商品、订单、用户等多个实体类,每个实体类都有一系列的增删改查操作。如果不使用泛型,针对每个实体类都得编写重复的数据库访问代码,这无疑是一场噩梦😫。

以查询操作为例,对于商品实体:

public class ProductRepository
{public Product GetProductById(int id){// 数据库连接、查询语句等操作,此处简化示意return new Product(); }
}

对于订单实体:

public class OrderRepository
{public Order GetOrderById(int id){// 类似的数据库操作,重复且易错return new Order(); }
}

有了泛型,我们可以创建一个通用的仓储基类:

public class GenericRepository<T> where T : class
{public T GetById(int id){// 通用的数据库连接、查询逻辑,根据传入的实体类型 T 动态构建查询return default(T); }
}

然后,商品、订单等实体对应的仓储类只需继承这个泛型基类:

public class ProductRepository : GenericRepository<Product> {}
public class OrderRepository : GenericRepository<Order> {}

这样,不仅减少了大量重复代码,还使得代码结构更加清晰,后期维护与扩展也变得轻而易举,为电商系统的稳定运行与快速迭代奠定了坚实基础,让业务逻辑的实现更加高效、可靠🚀。

六、探索进阶:泛型的更多宝藏

在初步领略了泛型的强大魅力之后,让我们进一步探索它的进阶奥秘,这些进阶特性将如同为我们的编程羽翼添上绚丽的彩羽,助力我们在代码的天空飞得更高更远🛫。

泛型接口是泛型家族中的重要一员,它允许我们定义一套通用的行为规范,而不局限于特定的数据类型。例如,我们定义一个泛型接口 IRepository:

public interface IRepository<T>
{void Add(T item);void Delete(T item);T GetById(int id);
}

不同的数据实体类,如 Product、Order、User 等,只需实现这个泛型接口,就能遵循统一的增删查操作规范,代码的一致性与扩展性瞬间提升,就像为不同品牌的手机都配备了统一标准的充电接口,通用性大大增强。

泛型委托则为方法的传递与调用带来了极大的灵活性。想象一下,我们有一个需求是对不同类型的列表进行排序,传统方式可能需要为每种类型编写特定的排序方法,但有了泛型委托,我们可以这样做:

public delegate int Comparison<T>(T x, T y);public static void Sort<T>(T[] array, Comparison<T> comparer)
{// 排序算法实现,依据传入的比较委托进行元素比较与排序
}

通过定义 Comparison 泛型委托,我们可以灵活传入不同类型的比较逻辑,无论是整数的大小比较,还是自定义对象根据特定属性的比较,都能轻松驾驭,代码复用性达到新高度,仿佛拥有了一把万能的排序钥匙,能打开各种数据类型排序的大门。

而 where 子句(约束)更是为泛型的精准应用保驾护航。比如,我们创建一个泛型方法用于计算两个数的乘积:

public static double Multiply<T>(T num1, T num2) where T : struct, IConvertible
{return num1.ToDouble(null) * num2.ToDouble(null);
}

这里的 where T : struct, IConvertible 约束就像一道精准的滤网,确保传入的类型参数 T 必须是可转换为数值的结构体,避免了错误类型数据的传入,让泛型方法在安全的轨道上高效运行,如同为精密仪器配备了精准的过滤器,保障运行的精准无误。

这些进阶特性仅仅是泛型宝藏的冰山一角,深入挖掘下去,你会发现更多的惊喜与强大功能,它们将持续赋能我们的编程之旅,让代码更加优雅、高效、健壮💪。

七、总结:拥抱泛型,编程升级

至此,我们一同深入探索了 C# 泛型这一强大特性,领略了它在类型安全与代码复用方面的卓越风姿💃🕺。

通过泛型,我们为代码披上了坚固的类型安全铠甲,让那些恼人的类型错误在编译阶段就无所遁形;同时,它又为我们递上了代码复用的万能钥匙,开启了高效开发的大门,无论是面对简单的数据处理,还是复杂的项目架构,都能游刃有余。

在未来的编程旅程中,希望大家积极拥抱泛型,将其巧妙运用到每一个合适的角落,持续优化代码,提升软件质量🚀。编程之路漫漫,让我们保持探索精神,不断挖掘 C# 及其他技术的更多宝藏,向着更高的编程巅峰奋勇攀登,书写属于我们的精彩代码篇章✍!a

相关文章:

类型安全与代码复用的C# 泛型

一、引言&#xff1a;泛型 ——C# 编程的神奇钥匙 在 C# 编程的广袤天地里&#xff0c;泛型宛如一把神奇钥匙&#xff0c;能够开启高效、灵活且安全的代码之门&#x1f6aa;。 想象一下&#xff0c;你是一位经验丰富的建筑师&#xff0c;要建造各种各样的房子&#x1f3e0;。…...

卷积神经05-GAN对抗神经网络

卷积神经05-GAN对抗神经网络 使用Python3.9CUDA11.8Pytorch实现一个CNN优化版的对抗神经网络 简单的GAN图片生成 CNN优化后的图片生成 优化模型代码对比 0-核心逻辑脉络 1&#xff09;Anacanda使用CUDAPytorch2&#xff09;使用本地MNIST进行手写图片训练3&#xff09;…...

vscode使用Marscode编程助手

下载 vscode 在插件里下载Marscode编程助手 插件完成 在这里点击安装&#xff0c;点击后这里出现AI编程插件。...

网络分析仪测试S参数

S参数的测试 一&#xff1a;S参数的定义 S参数&#xff08;Scattering Parameters&#xff0c;散射参数&#xff09;是一个表征器件在射频信号激励下的电气行为的工具&#xff0c;它以输入信号、输出信号为元素的矩阵来表现DUT的“传输”和“散射”效应&#xff0c;输入、输出…...

docker mysql5.7如何设置不区分大小写

环境 docker部署&#xff0c;镜像是5.7&#xff0c;操作系统是centos 操作方式 mysql 配置文件是放在 /etc/mysql/mysql.conf.d/mysqld.cnf&#xff0c; vim /etc/mysql/mysql.conf.d/mysqld.cnf lower_case_table_names1 重启mysql容器 验证 SHOW VARIABLES LIKE low…...

【1】Word:邀请函

目录 题目 文字解析 流程 题目 文字解析 考生文件夹☞Word.docx☞一定要用ms打开&#xff0c;wps打开作答无效☞作答完毕&#xff0c;F12或者手动另存为&#xff08;考生文件夹&#xff1a;路径文件名&#xff09; 注意&#xff1a;一定要检查&#xff0c;很有可能你前面步…...

【gin】中间件使用之jwt身份认证和Cors跨域,go案例

Gin-3 中间件编程及 JWT 身份认证 1. Gin 中间件概述 中间件是处理 HTTP 请求的函数&#xff0c;可以在请求到达路由处理函数之前或之后对请求进行处理。 在 Gin 框架中&#xff0c;中间件常用于处理日志记录、身份验证、权限控制等功能。 router : gin.Default() router.Us…...

【JAVA实战】@FeignClient注解类通用请求封装

背景 最近在编写多个系统数据集成过程中&#xff0c;经常会使用到FeignClient注解标记一个类&#xff0c;类里面编写很多请求方法&#xff0c;如果第三方系统有非常多的URL请求&#xff0c;每个方法对应一个URL请求&#xff0c;那么这个类就会非常的庞大&#xff0c;是否有一种…...

[c语言日寄]精英怪:三子棋(tic-tac-toe)3命慢通[附免费源码]

哈喽盆友们&#xff0c;今天带来《c语言》游戏中[三子棋boss]速通教程&#xff01;我们的目标是一边编写博文&#xff0c;一边快速用c语言实现三子棋游戏。准备好瓜子&#xff0c;我们计时开始&#xff01; 前期规划 在速通中&#xff0c;我们必须要有清晰的前期规划&#xf…...

GORM(Go语言数据交互库)

GORM&#xff08;Go ORM&#xff0c;即对象关系映射&#xff09;是Go语言中非常流行且功能强大的数据库交互库。它简化了与关系型数据库的交互过程&#xff0c;提供了丰富的API来处理各种数据库操作。下面将详细介绍GORM的功能、使用方法和一些高级特性。 1. 安装 首先&#…...

Redis主从同步是怎么实现的?

Redis主从同步是怎么实现的&#xff1f; 主从节点建立连接后&#xff0c;从节点会进行判断&#xff1a; 1.如果这是从节点之前没有同步过数据 属于初次复制&#xff0c;会进行全量重同步&#xff0c;那么从节点会向主节点发送PSYNC?-1 命令&#xff0c;请求主节点进行全量重…...

Flutter中Get.snackbar避免重复显示的实现

在pubspec.yaml中引入依赖框架。 #GetX依赖注解get: ^4.6.5创建一个SnackBarManager管理类去管理每个提示框。 import package:get/get.dart; import package:flutter/material.dart;class SnackBarManager {factory SnackBarManager() > instance;static final SnackBarMa…...

[Qt]常用控件介绍-多元素控件-QListWidget、QTableWidget、QQTreeWidget

目录 1.多元素控件介绍 2.ListWidget控件 属性 核心方法 核心信号 细节 Demo&#xff1a;编辑日程 3.TableWidget控件 核心方法 QTableWidgetItem核心信号 QTableWidgetItem核心方法 细节 Demo&#xff1a;编辑学生信息 4.TreeWidget控件 核心方法 核心信号…...

深入Android架构(从线程到AIDL)_32 JNI架构原理_Java与C的对接05

1、EIT造形观点 基于熟悉的EIT造形&#xff0c;很容易理解重要的架构设计决策议题。 前言 2、混合式EIT造形 一般EIT造形是同语言的。也就是<E>、 <I>和<T>都使用同一种语言撰写的&#xff0c;例如上述的Java、 C/C等。于此&#xff0c;将介绍一个EIT造…...

【gRPC】clientPool 客户端连接池简单实现与go案例

什么是 gRPC 客户端连接池&#xff1f; 在 gRPC 中&#xff0c;创建和维护一个到服务器的连接是非常消耗资源的&#xff08;比如 TCP 连接建立和 TLS 握手&#xff09;。 而在高并发场景下&#xff0c;如果每次请求都创建新的连接&#xff0c;不仅会导致性能下降&#xff0c;还…...

Android 15应用适配指南:所有应用的行为变更

Android系统版本适配&#xff0c;一直是影响App上架Google Play非常重要的因素。 当前Google Play政策规定 新应用和应用更新 必须以 Android 14&#xff08;API 级别 34&#xff09;为目标平台&#xff0c;才能提交到Google Play。现有应用 必须以 Android 13&#xff08;AP…...

24-25-1-单片机开卷部分习题和评分标准

依据相关规定试卷必须按评分标准进行批改。 给分一定是宽松的&#xff0c;能给分一定给&#xff0c;如有疑问也可以向学院教务办申请查卷。 一部分学生期末成绩由于紧张或其他原因导致分数过低&#xff0c;也是非常非常遗憾的。 个人也是非常抱歉的。 开卷考试 简答题 第一…...

STM32第6章、WWDG

一、简介 WWDG&#xff1a;全称Window watchdog&#xff0c;即窗口看门狗&#xff0c;本质上是一个能产生系统复位信号和提前唤醒中断的计数器。 特性&#xff1a; 是一个递减计数器。 看门狗被激活后&#xff0c; 当递减计数器值从 0x40减到0x3F时会产生复位&#xff08;即T6位…...

汽车免拆诊断案例 | 2007 款法拉利 599 GTB 车发动机故障灯异常点亮

故障现象  一辆2007款法拉利599 GTB车&#xff0c;搭载6.0 L V12自然吸气发动机&#xff08;图1&#xff09;&#xff0c;累计行驶里程约为6万km。该车因发动机故障灯异常点亮进厂检修。 图1 发动机的布置 故障诊断 接车后试车&#xff0c;发动机怠速轻微抖动&#xff0c;…...

C语言-数据结构-队列

目录 1.队列的特点 2.队列的实现 2.1.初始化队列 2.2.入队列 2.2.1.入空队列 2.2.2.入非空队列 2.3.出队列 2.4.销毁队列 2.5.完整代码 3.实际应用 1.队列的特点 队列是一种常见的数据结构&#xff0c;它遵循先进先出&#xff08;FIFO, First In First Out&#xff09…...

STL之VectorMapList针对erase方法踩坑笔记

前沿 如下总结的三种容器&#xff0c;开头都会涉及当前容器的特点&#xff0c;再者就本次针对erase方法的使用避坑总结。 一.Vector vector关联关联容器&#xff0c;存储内存是连续&#xff0c;且特点支持快速访问&#xff0c;但是插入和删除效率比较地(需要找查找和移动)。另…...

梯度下降法为什么要提前停止

什么是提前停止&#xff08;Early Stopping&#xff09;&#xff1f; 提前停止是一种正则化技术&#xff0c;用于在训练机器学习模型&#xff08;特别是神经网络&#xff09;时防止过拟合。它的核心思想是通过监控模型在验证集上的性能&#xff0c;在性能开始恶化之前停止训练…...

【vue3项目使用 animate动画效果】

vue3项目使用 animate动画效果 前言一、下载或安装npm 安装 二、引入组件三、复制使用四、完整使用演示总结 前言 提示&#xff1a;干货篇&#xff0c;不废话&#xff0c;点赞收藏&#xff0c;用到会后好找藕~ 点击这里&#xff0c;直接看官网哦 &#x1f449; 官网地址&#…...

1.1.1 C语言常用的一些函数(持续更新)

总框架见&#xff08;0. 总框架-CSDN博客&#xff09; &#xff08;1&#xff09;socket (a)分配fd&#xff1b;(b)分配tcp控制块(tcb) int socket(int domain, int type, int protocol);AF_INET IPv4 Internet protocols ip(7)AF_INET6 IP…...

李宏毅机器学习课程笔记03 | 类神经网络优化技巧

文章目录 类神经网络优化技巧局部最小值local minima 与 鞍点saddle pointSaddle Point 的情况更常见 Tips for training&#xff1a;Batch and MomentumSmall Batch vs Large Batch回顾&#xff1a;optimization优化 找到参数使L最小问题&#xff1a;为什么要用Batch&#xff…...

简洁明快git入门及github实践教程

简洁明快git入门及github快速入门实践教程 前言git知识概要&#xff1a;一&#xff1a;什么是 Git&#xff1f;二&#xff1a;安装 Git三&#xff1a;配置 Git配置git的用户名和邮箱地址创建仓库 四&#xff1a;Git实践五&#xff1a;远程仓库操作&#xff08;基于git命令使用G…...

Python使用socket实现简易的http服务

在接触的一些项目中&#xff0c;有时为了方便可视化一些服务状态&#xff08;请求数很少&#xff09;&#xff0c;那么很容易想到使用http服务来实现。但开源的web后端框架&#xff0c;例如flask&#xff0c;fastapi&#xff0c;django等略显沉重&#xff0c;且使用这些框架会有…...

【Hive】海量数据存储利器之Hive库原理初探

文章目录 一、背景二、数据仓库2.1 数据仓库概念2.2 数据仓库分层架构2.2.1 数仓分层思想和标准2.2.2 阿里巴巴数仓3层架构2.2.3 ETL和ELT2.2.4 为什么要分层 2.3 数据仓库特征2.3.1 面向主题性2.3.2 集成性2.3.3 非易失性2.3.4 时变性 三、hive库3.1 hive概述3.2 hive架构3.2.…...

linux系统监视(centos 7)

一.系统监视 1.安装iostat&#xff0c;sar&#xff0c;sysstat&#xff08;默认没有&#xff0c;安装过可以跳跃&#xff09; iostat 和 sar&#xff1a; 同样&#xff0c;iostat 和 sar 是 sysstat 软件包的一部分。使用以下命令安装&#xff1a;sudo yum install sysstat解释…...

Blazor中Syncfusion图像编辑器组件使用方法

Blazor中Syncfusion图像编辑器组件是一个功能丰富的图像处理工具&#xff0c;支持多种编辑、操作和交互方式&#xff0c;帮助用户高效处理图像。以下是该组件的主要功能总结&#xff1a; 主要功能&#xff1a; 图像打开与保存 图像编辑器允许用户通过简单的点击操作打开支持的…...