C#.Net筑基-类型系统①基础

image.png

C#.Net的BCL提供了丰富的类型,最基础的是值类型、引用类型,而他们的共同(隐私)祖先是 System.Object(万物之源),所以任何类型都可以转换为Object。


01、数据类型汇总

C#.NET 类型结构总结如下图,Object是万物之源。最常用的就是值类型、引用类型,指针是一个特殊的值类型,泛型必须指定确定的类型参数后才是一个正式的类型。

image

1.1、值类型汇总⭐

🔸值类型Type说明示例/备注
byteSystem.Byte8 位(1字节)无符号整数,0到255,
sbyteSystem.SByte8 位(1字节)有符号整数,-128 到 127不符合 CLS
intSystem.Int3232位(4字节)有符号整型,大概-21亿-21亿
uintSystem.UInt3232位(4字节)无符号整型, 0 到 42亿不符合 CLS
shortSystem.Int1616 位(2字节)有符号短整数,-32768 到 32767,
ushortSystem.UInt1616 位(2字节)无符号 短整数, 0 到 65535不符合 CLS
longSystem.Int6464位(8字节)有符号长整形,19位数
ulongSystem.UInt6464位(8字节)无符号长整形,20位数不符合 CLS
Int128Int128128 位有符号整数,.Net7支持
BigIntegerBigInteger表示任意大小的(有符号)整数,不可变值
整数表示-十六进制:0x/0X前缀;二进制:0b/0B前缀var默认为int
floatSystem.Single32位(4字节)单精度浮点数,最多6-7 位小数,-+3.402823E38后缀f/F
doubleSystem.Double64位(8字节)双精度浮点数,最多15-16 位小数,-+1.7*E308后缀d/D
decimalSystem.Decimal128位(16字节)高精度浮点数,28位小数,-+7.9E28后缀m/M
boolSystem.Boolean8位(1字节)布尔型,只有两个值:truefalse
charSystem.Char16 位(2字节)单个字符,0 到 65,535的码值,使用 UTF-16 编码
enumSystem.Enum支持任意整形的(常量)枚举,可以看做是一组整形的常量值集合
ComplexComplex表示一个复数,实部和虚部都为double
GuidGuid全局唯一标识符(16字节),一出生就是全球唯一的值Guid.NewGuid()
struct结构体是一种用户自定义的值类型,常用于定义一些简单(轻量)的数据结构
DateTimeDateTime时间日期,详见下一章节

  • bool 虽然只需要1位空间,但仍然占用了1个字节,是因为字节是处理器的最小单位。如果有大量的Bool,可用BitArray。
  • 值类型大多都是“不可变的”,就意味着修改会创建新的对象,上面表格中除了自定义的结构体Struct外都是不可变的。
  • CTS(Common Type System)为通用类型系统,为微软定制的通用类型规范,所有.Net语言都支持(如F#、VB、C#)。不符合CTS就意味着C#独有。

1.2、引用类型汇总⭐

🔸引用类型Type说明示例/备注
objectSystem.Object.NET 类的顶层基类,万物之源,包括所有值类型、引用类型万物之源
stringSystem.String字符串,引用类型,使用上有点像值类型恒定性、驻留性
dynamicSystem.Dynamic动态类型,编译时不检查,可随意编码,只在运行时检查dynamic = 12
Interface-严格来说并不是“类型”,只是一组契约,可作为引用申明变量接口契约
Class-定义一个引用类型,隐式继承自object定义类
DelegateSystem.Delegate委托类型,详见后文《解密委托与事件》
IEnumerable-可枚举集合接口,几乎所有集合类型都实现了该接口
T[]Array数组,同上枚举接口,更多参考《.Net中的集合》
匿名类型new{P=v,V=1}动态申明一个临时匿名类型实例,编译器会创建类
元祖Tuple内置的一组包含若干属性的泛型类,常用(ValueTuple)编译器支持
recoredrecord记录类型,支持class(默认)、struct,其实就是简化版的类型申明编译器创建完整类型

1.3、Object-万物之源

System.Object是所有类型的根,任何类都是显式或隐式的继承于System.Object,包括值类型,所以任何类型都可以转换为Object

成员描述
string? ToString ()返回对象的字符串,默认返回对象类型名称,按需重写。
bool Equals (object? obj)比较是否与当前(this)相同,引用类型比较引用地址,值类型比较值&类型,可重写!
int GetHashCode ()获取当前对象的哈希码,用于哈希集合Dictionary、Hashtable中快速检查相等性。但不可用于相等判断,如果重写了Equals,应同时重写GetHashCode,确保两者一致。
Type GetType ()当前实例的准确运行时类型。如果是类型,在可用typeof(T)
protected ~Object ();Object.Finalize析构函数,GC调用释放资源,按需实现。一般配合Dispose(GC.SuppressFinalize )
protected object MemberwiseClone()浅拷贝,创建新对象>赋值非静态字段,引用类型字段就是赋值引用地址了。
static bool Equals(Object, Object)比较相同,内部会调用实例的Equals(Object)方法
static bool ReferenceEquals(o1,o2)比较两个引用对象是否同一实例,⁉️注意如果用于值类型会被装箱从而始终false

下面代码为.Net中的 System.Object 源码:

public partial class Object
{public Object(){ }public virtual string? ToString(){return GetType().ToString();}protected internal unsafe object MemberwiseClone();  //对象浅拷贝public virtual bool Equals(object? obj){return this == obj;}public static bool Equals(object? objA, object? objB){return objA == objB || (objA != null && objB != null && objA.Equals(objB));}public static bool ReferenceEquals(object? objA, object? objB){return objA == objB;}public virtual int GetHashCode(){return RuntimeHelpers.GetHashCode(this);}~Object(){}  //终结器
}

02、值类型与引用类型

值类型和引用类型是C#中最重要、最常用的两种数据类型,两者是有很多区别的,而且常常和性能有很大关系,因此这是C#开发者必须掌握的基础知识。

2.1、值类型 VS 引用类型

区别值类型 ValueType引用类型 ReferenceType
⭐存储位置栈(Stack),也可以称为线程栈堆(GC Heap),由GC管理
⭐存储内容对象在堆上,引用变量在栈上,栈存储的的是堆上对象的内存地址
⭐传递方式值传递,参数传递时传递的是值拷贝,各回各家传递的是引用(地址),因此是同一个对象,分身代理
装箱、拆箱转换为object、接口时会装箱、拆箱
默认值default数字、枚举默认0,bool默认false默认null
占用内存大小就值本身的长度,如int为4个字节值本身+额外空间(引用对象的标配:TypeHandle、同步块)
继承的对象隐式继承自System.ValueType默认继承自Object
接口、继承不支持继承其他值类型,可继承接口支持继承类、接口
怎么判断Type.IsValueTypeo.GetType().IsValueTypeIsValueType ==false
生命周期作用域结束就释放,或方法结束就释放了由GC管理,当对象没被使用了,GC检查后标记清除
性能栈内存性能很高低,需要GC分配内存、GC释放
  • default可以表示任意类型的默认值,编译时会被赋值。struct的默认值为每个字段设置默认值。
int x = 100;
int y = x;     //值拷贝传递
string name = "sam";
int[] arr = new int[] { 1, 2, 3 };
var list = arr; //引用地址传递,实际指向同一个引用对象,分身幻象

📢 两者核心区别就是存储的方式不同,理解这一点非常重要,在变量(字段)赋值、方法参数传递上都是如此。

image

🔸Stack 栈:(线程)栈,由操作系统管理,存放值类型、引用类型变量(就是引用对象在托管堆上的地址)。栈是基于线程的,也就是说一个线程会包含一个线程栈,线程栈中的值类型在对象作用域结束后会被清理,效率很高。

🔸托管堆(GC Heap):进程初始化后在进程地址空间上划分的内存空间,存储.NET运行过程中的对象,所有的引用类型都分配在托管堆上,托管堆上分配的对象是由GC来管理和释放的。托管堆是基于进程的,当然托管堆内部还有其他更为复杂的结构。

关于更多堆栈内存信息,查看后文《C#的内存管理艺术》

📢值类型可使用outref关键字,像引用类型一样传递参数地址。两者对于编译器是一样的,都是取地址,唯一区别就是ref参数需要在外面初始化,out参数在方法内部初始化。

2.3、装箱和拆箱⁉️

因为值类型、引用类型的基类都是Object,因此值类型、引用类型是可以相互转换的,但这个转换是有很高成本的,这个过程就是装箱、拆箱。

int x = 100;     //一个普通的值类型变量
object obj =x;   //装箱到obj
int y = (int)obj;//拆箱到y

可视化分析一下这个过程:

🔸装箱:值类型转换为引用对象,一般是转换为System.Object类型,或接口类型。所以“箱子”就是Object引用对象,装箱的过程:

  • ❶ 在GC堆上申请内存,内存大小为值类型的大小,再加上额外固定空间(引用类型的标配:TypeHandle和同步索引块);
  • ❷ 将值(100)拷贝到分配的内存中;
  • ❸ 返回新对象(箱子)的引用地址给变量obj

🔸拆箱:引用类型转换为值类型,注意,这里的引用类型只能是被装箱的引用类型对象。

  • ❶ 检测操作是否合法,如箱子是否为null,类型是否和待拆箱的类型一致,检测失败则抛出异常InvalidCastException
  • ❷ 把箱子中的值拷贝到栈上。

image.png

上面三行装箱、拆箱代码的IL代码:装箱box、拆箱unbox是两个专门的指令。

image.png

由上可知,装箱会在GC堆上创建一个“箱子”(Object对象)来装载值,这是装箱造成极大的性能损失的根本原因,拆箱则把值搬回到栈内存上。

  • 只有值类型才会有装箱、拆箱,引用类型一直都在“箱子”里。
  • 相对来说装箱的性能损失更大,原因不难理解,创建引用对象(箱子)的性能开销更大。

📢在日常开发中,很容易发生隐式装箱,所以要特别注意,尽量用泛型。如ArrayList、Hashtable 都是面向Object的集合,应该用List<T>Dictionary<TKey, TValue>代替。

ArrayList arr = new ArrayList();
arr.Add(1);      //装箱
arr.Add(true);   //装箱
Hashtable ht = new Hashtable();
ht.Add(1,1.2f);  //装箱了两次

对比测试装箱、拆箱的性能影响:

private T Add<T>(T arg1,T arg2) where T:INumber<T>
{return arg1+arg2;
}
private int AddWithObject(object x, object y)
{return (int)x + (int)y;
}

测试结果比较明显,装箱的方法在执行效率、内存消耗上都要差很多。

image.png


03、Nullable?可空类型

可空类型可用于值类型、引用类型,他们使用语法类似,不过他们是完全不同的两种东西。值类型的可空?是一个泛型Nullable<T>类型,而引用类型的?只是一个用于编译器检查的语法。

image.png

int? n = null;
string? str = "sam";

可空值类型、引用类型都支持null操作符:

  • Null 条件运算符,str?.Length
  • Null 合并赋值,n??=1

3.1、值类型的Nullable<T>

对于值类型,可空值类型表示值类型对象可以为null值,可空值类型T?的本质其实是Nullable<T>,他是一个值类型(结构体)。

int x0 = default;  //默认值为0
int? x1 = default; //默认值值为null
int? x2 = null;
Nullable<int> x3 = null;  //同上if (x3.HasValue)
{Console.WriteLine(x3.Value);
}
int a = x0 + (x3.HasValue? x3.Value : 10);
int b = x0 + x3 ?? 10; //效果同上
  • 简化的语法为:Type?,示例:int? n;,类型后跟一个问号"?",和引用类型的可空语法一样。
  • 属性HasValue判断是否有值,Value获取值,如果HasValuefalse时获取 Value 值会抛出异常。
  • 转换:T可隐式转换为T?,反之则需要显示转换。

下面为Nullable<T>的源码,是一个简单的结构体,T被约束为结构体(值类型)。

public struct Nullable<T> where T : struct
{//判断是否有值public readonly bool HasValue { get; }//获取值public readonly T Value { get; }public readonly T GetValueOrDefault()public readonly T GetValueOrDefault(T defaultValue)
}

image.png

3.2、可空引用类型T?

引用类型本身的默认值就是null,为了避免一些场景下不必要的 NullReferenceException,就有了可空的引用类型T?,其核心目的就是为提高代码的健壮性。可空的引用类型并不是一个“新的类型”,而是一个编译指令,告诉编译器这个引用类型变量可能是null,使用时需检查,未初始化也没检查null就使用,编译器会产生编译告警,由此来提前发现潜在Bug,提高代码健壮性。如果没加?,则该表示引用对象不会为null

要开启可空引用类型需要配置启用才行:

  • 在项目配置中开启:<Nullable>enable</Nullable>,值disable表示不启用。
  • 在代码文件中启用,在文件头部加#nullable enable,只对当前代码文件有效。
public int GetLength(string? firstName, string lastName)
{var len = firstName.Length; //编译器会警告 firstName 可能为nullif (firstName != null)      //加上null判断就好了len += firstName.Length;len = firstName!.Length;    //加上!,则忽略检查len += lastName.Length;     //lastName不会为null,没有告警return len;
}

对于上面的示例代码,编译器会认为firstName可能会为null,在使用前必须初始化,或者检查是否为null。而lastName不会为null,可以直接使用。

📢 消除可空引用类型的编译告警的方法是结尾加!(null 包容运算符),告诉编译器这个对象肯定不会为null,别再告警了!

在命名空间“System.Diagnostics.CodeAnalysis”下还有一些特性,用来辅助代码的静态检查和编译器检查。

[NotNull]  //标记返回值不会为null
private string? FullName => "sam";//当方法返回false时参数value不会为null。该方法就是string.IsNullOrEmpty的源码
public static bool IsNullOrEmpty([NotNullWhen(false)] string? value)
{if ((object)value != null){return value.Length == 0;}return true;
}

04、类型转换⭐

数据类型之间是可以相互转换的,由一个数据类型转换为另一数据类型,常见的转换方式:

转换方式说明备注/示例
隐式转换转换是自动的,一般是兼容的数值类型之间,编译时检查int n =100; float f = n;
强制显示转换使用强制转换操作符转换,(Type)value值类型编译时检查,引用类型运行时检查,失败抛出异常!
装箱、拆箱值类型转换为引用类型object,反之为拆箱装箱是隐式的,拆箱需显示转换
as显示转换只用于引用类型转换:value as Type运行时检查,失败返回null
is类型检查检查一个值是否为指定(兼容)类型,如果是则转换if(obj is float f) {}
类型方法Parse内置值类型基本都提供Parse、TryParse方法int.Parse("123")
Convert静态类,提供了大量的静态方法来转换内置数据类型Convert.ToInt16(false)
BitConverter静态类,各种内置类型和字节之间的转换方法BitConverter.GetBytes(0xff)
XmlConvert静态类,提供了各种内置类型和string之前的转换方法XmlConvert.ToInt32("1221")
TypeConverterSystem.ComponentModel 空间下提供的大量类型转换器var cc = TypeDescriptor.GetConverter(typeof(Color))
dynamic动态类型并不算是类型转换,作为一种特殊方式,运行时检查dynamic d = Foo; d.Print();

📢注意

  • 几乎所有类型都可以隐式转换为 Object,注意值类型转换Object会装箱。
  • 对于值类型,范围小的类型转换范围大的类型大都支持隐式转换,且不会损失精度,如floatdoubleint转浮点数。反之则需要强制转换,可能会损失精度,或溢出。
  • is 语句可用于模式匹配,实现灵活的类型、数据检查,详细参考《C#中的模式匹配汇总》。
int a = (int)'a';     // 强制类型转换
Console.WriteLine(a); // 97float f = a;          // 隐式类型转换
Console.WriteLine(f);object obj = f;         //装箱,值类型隐式转换为引用类型
float f2 = (float)obj;  //拆箱
if(obj is float f3)     //is检查是否为float类型,如果是则转换值到变量f3
{Console.WriteLine(f3);
}
string str = obj as string; //as 转换失败,obj是float装箱
Console.WriteLine(str);     //null

4.1、数值转换方式汇总

转换需求转换方法示例
解析十进制数字Parse、TryParseint.Parse("1234")double.Parse("123.04")
解析2/8/16进制数Convert.To()Convert.ToInt32("F",16)//15
16进制格式化ToString(“X”)1234.ToString("X6")//0004D2
无损数值转换隐式转换int n = 100; double d = n;
截断数值转换显示转换 T v2 = (T)v1double d=12.56d; int n = (int)d; //n = 12,直接截断,不会四舍五入
四舍五入转换Convert.To()、Math.Round(d)int n = Convert.ToInt32(d); //n = 13,四舍五入转换
int n = Math.Round(d) //n = 13,可指定小数位数

05、相等、大小比较

📢 值类型比较的是值(结构体会比较其所有字段值),引用类型是比较的引用地址!

比较操作说明
==、!=相等运算符,其本质是调用静态方法(运算符重载方法)
a.Equals(b)实例的虚方法(可被重写),运行时根据实际类型调用。
🔸 ①、a不能为null,否则就NullReferenceException了。
🔸 ②、引用类型默认比较引用地址,值类型会递归调用每一个字段的Equals方法。
🔸 ③、装箱的值类型会比较箱子内的值。
Object.Equals(a,b)Object静态方法,null判断+a.Equals(b),参数是Object,值类型会装箱。
Object.ReferenceEquals(a,b)Object静态方法,只比较引用地址
IEquatable<T>相等接口方法bool Equals(T? other)
IComparable<T>大小比较 int CompareTo(T? other),返回一个int值:a.CompareTo(b)// a>b 返回1,a==b 返回 0, a<b 返回 -1
>、<大小比较运算符,结果应该和上面 IComparable 保持一致
IEqualityComparer<T>扩展的相等比较接口,非泛型版本 IEqualityComparer
StringComparer提供了用于字符串的多种类型的比较器:StringComparer.Ordinal.Compare("h","H")
public interface IComparable<in T>
{int CompareTo(T? other);
}
public interface IEquatable<T>
{bool Equals(T? other);
}
public interface IEqualityComparer<in T>
{bool Equals(T? x, T? y);int GetHashCode([DisallowNull] T obj);
}
// System.Object
public static bool Equals(object? objA, object? objB)
{if (objA == objB){return true;}if (objA == null || objB == null){return false;}return objA.Equals(objB);
}
  • Equals()方法必须自相等,即 x.Equals(x) 必为true
  • 对于值类型,大多数情况下Equals()方法等效于 ==,只有double.NaN例外,double.NaN 不等于任何对象。而引用类型则不一定了,有些引用类型重写了Equals()方法,而没有重写 == 运算符。
Console.WriteLine(double.NaN == double.NaN);     //False
Console.WriteLine(double.NaN.Equals(double.NaN));//TrueConsole.WriteLine(object.Equals(1,1));           //True  //装箱比较值
Console.WriteLine(object.ReferenceEquals(1,1));  //False //装箱比较引用StringBuilder sb1 = new StringBuilder("sb");
StringBuilder sb2 = new StringBuilder("sb");
Console.WriteLine(sb1 == sb2);                     //False
Console.WriteLine(object.Equals(sb1,sb2));         //False
Console.WriteLine(object.ReferenceEquals(sb1,sb2));//False
Console.WriteLine(sb1.Equals(sb2));				   //True  //与上面的 object.Equals(sb1,sb2) 不同

上面的 StringBuilder 重新实现了 Equals方法,但不是继承覆盖,而是隐式new覆写实现的,因此只能在 通过 StringBuilder 引用调用时才有效。参考:StringBuilder 源码。

image.png

5.1、自定义相等

⁉️什么时候需要自定义相等比较?

  • 提高比较速度,多用于自定义结构体。
  • 修改相等比较的语义,基于实际业务需要自定义相等的规则,如System.Url、String.String 都是引用类型,只要字符值相同则相等(== 和 Equals)。

⁉️如何自定义相等比较?

  • 重写 GetHashCode()Equals() 方法。这两个一般是一起配对重写,需注意 二者的一致性。
  • (可选)重载 !===
  • (可选)实现 IEquatable<T> 接口。

📢GetHashCode() 是基类 Object 的一个虚方法,该方法用于获取一个对象的 Int32 类型的散列码。该散列码只在键值结构(Hashtable、HashSet、Dictionary)中使用,用来表示元素的唯一“ID”,用于在哈希表中快速检索数据。

GetHashCode()的默认实现:

  • 值类型的散列码 是由每一个字段的值来计算的,如果有多个字段则通过一定的规则组合(如异或运算)。
  • 引用类型则基于对象的内存地址。

so,如果重写了Equals() 方法,则一般要重写GetHashCode(),让两者匹配。当然如果不遵守该规则也没问题,只是在使用哈希表时可能会出现问题(如性能严重下降)。


参考资料

  • .NET类型系统②常见类型
  • C# 文档
  • 《C#8.0 In a Nutshell》
  • .NET面试题解析(02)-拆箱与装箱
  • .NET面试题解析(01)-值类型与引用类型

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/27661.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

项目采购管理

目录 1.概述 2.三个子过程 2.1.规划采购管理 2.2.实施采购 2.3.控制采购 2.4.归属过程组 3.应用场景 3.1.十个应用场景 3.2.软件开发项目 3.2.1. 需求识别和分析 3.2.2. 制定采购计划 3.2.3. 发布采购请求 3.2.4. 供应商评估与选择 3.2.5. 合同签订 3.2.6. 采购…

Unity动态添加聊天文本

1.创建一个滚动视图 2.调整滚动视图的位置并删掉这个 3.创建一个输入框和一个按钮 这里插一句一定要给content添加这个组件并设置单元格大小 4创建一个脚本并编写下面代码 using System.Collections; using System.Collections.Generic; using TMPro; using Unity.VisualScrip…

YouTube583美元账户做到一千多万美元,125万粉的顶级交易员

油管125万粉丝的Ross Cameron,一位把583美元账户做到一千多万美元。他说他曾经也是像无头苍蝇一样交易,最终凄惨爆仓,也就是在爆仓之后,他终于开始沉下心来研究交易策略,终于终于,他有一天找到了交易模型,并用它执行至今。 Ross Cameron无疑是最成功的日内交易员之一,而…

The Google File System 论文阅读

2003年USENIX&#xff0c;出自谷歌&#xff0c;开启分布式大数据时代的三篇论文之一 总体设计 假设 硬件损坏是常态&#xff0c;而非意外。例如磁盘损坏&#xff0c;断电&#xff0c;断网。所以持续的监控&#xff0c;错误诊断&#xff0c;错误恢复要纳入系统设计之中文件很…

【文档智能 RAG】RAG增强之路-智能文档解析关键技术难点及PDF解析工具PDFlux

前言 在私域知识问答和企业知识工程领域&#xff0c;结合Retrieval-Augmented Generation&#xff08;RAG&#xff09;模型和大型语言模型&#xff08;LLM&#xff09;已成为主流方法。然而&#xff0c;企业中存在着大量的PDF文件&#xff0c;PDF解析的低准确性显著影响了基于…

open-amv开发环境搭建

open-amv是基于rv1103主控芯片的视觉开发板子 1.板子使用 板子使用type c作为调试口&#xff0c;同时供电&#xff0c;请在电脑上下载adb&#xff0c;当板子通过tpye c与电脑连接后&#xff0c;执行命令adb shell就会进入到板子的linux系统命令行。 2.编译环境 2.1 搭建doc…

ipad协议已更新

mmtls 24算法&#xff0c;by golang 其他/v1/other POST/v1/other/GetPeopleNearby 查看附近的人 POST/v1/other/GetQrCode 获取二维码 同步消息/v1/ws GET/v1/ws/GetSyncMsg 同步消息&#xff0c;ws协议 消息/v1/message POST/v1/message/AddMessageMgr 添加要发送…

什么是无杂散动态范围 (SFDR)?为什么 SFDR 很重要?

有多种不同的规格可用于表征电路线性度。SFDR 指标是一种常用的规范。该指标定义为所需信号幅度与感兴趣带宽内杂散的比率&#xff08;图 1&#xff09;。 图 1. 显示 SFDR 指标的图表。 对于 ADC&#xff0c;SFDR 展示了 ADC 如何在存在大信号的情况下同时处理小信号。作为一个…

如何阅读?从阅读中学阅读—《海绵阅读法》

大家好&#xff0c;我是老三&#xff0c;最近读了《海绵阅读法&#xff1a;如何吸收一本书的精华》&#xff0c;第一次阅读教如何阅读的书&#xff0c;整理一番读书笔记&#xff0c;分享给大家。 读书动机 我前一阵子写了篇文章&#xff0c;2024Q1&#xff0c;盘点我看过的54本…

[Java基本语法] 逻辑控制与方法

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏:&#x1f355; Collection与数据结构 (92平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 &#x1f9c0;线程与…

一键解锁创意无界:高效AI生成古典肖像图片,轻松打造艺术化身

在数字化时代&#xff0c;创意与艺术的结合正逐渐改变我们的生活。你是否曾梦想过拥有一幅专属于自己的古典肖像画&#xff0c;却又苦于找不到合适的画师或高昂的费用而望而却步&#xff1f;现在&#xff0c;这一切都将成为现实&#xff01; 进入首助编辑高手的AI魔法智绘图板块…

你能不能手敲出Spring框架?

Spring最成功的地方在于创始人Rod Johnson提出的IOC、AOP核心理念&#xff0c;反而不是其本身的技术。技术上今天可以有Spring春天&#xff0c;明天就可以有Autumn秋天。 核心理念有多重要&#xff1f;就如1871年巴黎公社的失败。公社在对抗法国zf和普鲁士占领军的背景下成立&…

英伟达开源 3400 亿巨兽:98% 合成数据训出最强开源通用模型,性能对标 GPT-4o

NVIDIA 最近开源了其大型语言模型 Nemotron-4 340B&#xff0c;这是一个具有划时代意义的模型&#xff0c;它使用了高达 98% 的合成数据进行训练&#xff0c;并且在性能上与 GPT-4 相当。Nemotron-4 340B 包括基础模型、指令模型和奖励模型&#xff0c;支持 4K 上下文窗口、50 …

回答网友的一个Delphi问题

网友想在grid 中 加一个水印&#xff0c;俺就给他写了个例子。先靠效果&#xff1a; 这个例子 包含下面几步&#xff1a; 1、创建背景 dg_bmp:Tbitmap.Create; w: Image1.Picture.Bitmap.width; h: Image1.Picture.Bitmap.height; dg_bmp.width: w*2; dg_bmp.height: …

从入门到高手的99个python案例(2)

51. 列表和数组比较 - 列表通用&#xff0c;NumPy数组高效。 import numpy as np normal_list [1, 2, 3] np_array np.array([1, 2, 3]) print(np_array.shape) # 输出 (3,), 数组有形状信息 52. Python的内置模块datetime - 处理日期和时间。 from datetime import…

数据库MySQL——从0到1入门教程

Q:为什么需要MySQL&#xff1f; A:网络服务中&#xff0c;我们需要存储、管理大量的数据&#xff0c;并确保数据的安全、实现增删改查操作的高效&#xff0c;因此需要一个系统用来专门管理数据&#xff0c;以实现上述的高性能要求&#xff0c;数据库管理系统应需而生 八股如下…

自动化数据驱动?最全接口自动化测试yaml数据驱动实战

前言 我们在做自动化测试的时候&#xff0c;通常会把配置信息和测试数据存储到特定的文件中&#xff0c;以实现数据和脚本的分离&#xff0c;从而提高代码的易读性和可维护性&#xff0c;便于后期优化。 而配置文件的形式更是多种多样&#xff0c;比如&#xff1a;ini、yaml、…

pdf structuredClone is not defined 解决

问题 部分手机系统的浏览器 pdf v2版本会出现 structuredclone is not defined 的报错&#xff0c;这是因为浏览器过低 解决 查看structuredClone的浏览器兼容性 structuredClone api 文档 polyfill 网站下方有个 polyfill的网址入口 可以解决低版本的兼容问题 相应网址…

笨蛋学算法之LeetCodeHot100_3_最长连续序列(Java)

package com.lsy.leetcodehot100;import java.util.Arrays; import java.util.HashSet; import java.util.Set;public class _Hot3_最长连续序列 {public static int longestConsecutive(int[] nums) {//创建set去重//对重复的数字进行去重Set<Integer> set new HashSet…

融合心血管系统(CVS)多视角信号的新架构新策略

随着深度学习的发展和传感器的广泛采用&#xff0c;自动多视角融合&#xff08;MVF&#xff09;在心血管系统&#xff08;CVS&#xff09;信号处理方面取得了进展。然而&#xff0c;普遍的MVF模型架构通常将同一时间步骤但不同视角的CVS信号混合成统一的表示形式&#xff0c;忽…