C# 中的记录类型简介 【代码之美系列】
🎀🎀🎀代码之美系列目录🎀🎀🎀
一、C# 命名规则规范
二、C# 代码约定规范
三、C# 参数类型约束
四、浅析 B/S 应用程序体系结构原则
五、浅析 C# Async 和 Await
六、浅析 ASP.NET Core SignalR 双工通信
七、浅析 ASP.NET Core 和 MongoDB 创建 Web API
八、浅析 ASP.NET Web UI 框架 Razor Pages/MVC/Web API/Blazor
九、如何使用 MiniProfiler WebAPI 分析工具
十、浅析 .NET Core 中各种 Filter
十一、C#.Net筑基-类型系统
十二、C#.Net 筑基-运算符
十三、C#.Net筑基-解密委托与事件
十四、C#.Net筑基-集合知识大全
十五、C#.Net筑基 - 常见类型
十六、C#.NET体系图文概述—2024最全总结
十七、C# 强大无匹的模式匹配,让代码更加优雅
文章目录
- 🎀🎀🎀代码之美系列目录🎀🎀🎀
- 前言
- 一、何时使用记录
- 1.1 值相等性
- 1.2 不可变性
- 二、记录与类和结构的区别
- 三、属性定义的位置语法
- 四、 非破坏性变化
- 五、用于显示的内置格式设置
- 六、继承
- 6.1 派生记录类型中的位置参数
- 6.2 继承层次结构中的相等性
- 6.3 派生记录中的 with 表达式
- 6.4 派生记录中的 PrintMembers 格式设置
- 6.5 派生记录中的解构函数行为
- 七、泛型约束
- 🎀🎀🎀代码之美系列目录🎀🎀🎀
前言
C#
中的 记录 是一个 类 或 结构,它为使用数据模型提供特定的 语法
和 行为
。 record
修饰符指示编译器合成对主要角色存储数据的类型有用的成员。 这些成员包括支持值相等的 ToString()
和成员的重载。
一、何时使用记录
在下列情况下,请考虑使用记录 而不是
类或结构:
- 你想要定义依赖
值相等性
的数据模型。 - 你想要定义对象
不可变
的类型。
1.1 值相等性
对记录来说,值相等性
是指如果 记录类型
的两个变量 类型
相匹配,且所有 属性
和 字段
值都相同,那么记录类型的两个变量是相等的。 对于其他引用类型(例如类),相等性默认指引用相等性,除非执行了值相等性。 也就是说,如果类的两个变量引用同一个对象,则这两个变量是相等的。 确定两个记录实例的相等性的方法和运算符使用 值相等性
。
并非所有数据模型都适合使用值相等性。 例如,Entity Framework Core
依赖引用相等性,来确保它对概念上是一个实体的实体类型只使用一个实例。 因此,记录类型 不适合
用作 Entity Framework Core
中的实体类型。
如果不替代或替换相等性方法,则声明的类型将控制如何定义相等性:
对于 class
类型,如果两个对象引用内存中的同一对象,则这两个对象相等。
对于 struct
类型,如果两个对象是相同的类型并且存储相同的值,则这两个对象相等。
对于具有 record
修饰符(record class、record struct 和 readonly record struct)的类型,如果两个对象是相同的类型并且存储相同的值,则这两个对象相等。
record struct
的相等性定义与 struct 的相等性定义相同。 不同之处在于,对于 struct
,实现处于 ValueType.Equals(Object)
中并且依赖反射。 对于记录,实现由编译器合成,并且使用声明的数据成员。
一些数据模型需要引用相等性。 例如,Entity Framework Core
依赖于引用相等性来确保它对概念上是一个实体的实体类型只使用一个实例。 因此,记录和记录结构不适合用作 Entity Framework Core
中的实体类型。
下面的示例说明了记录类型的值相等性:
public record Person(string FirstName, string LastName, string[] PhoneNumbers);public static void Main()
{var phoneNumbers = new string[2];Person person1 = new("Nancy", "Davolio", phoneNumbers);Person person2 = new("Nancy", "Davolio", phoneNumbers);Console.WriteLine(person1 == person2); // output: Trueperson1.PhoneNumbers[0] = "555-1234";Console.WriteLine(person1 == person2); // output: TrueConsole.WriteLine(ReferenceEquals(person1, person2)); // output: False
}
1.2 不可变性
不可变类型 会 阻止
你在对象实例化后 更改
该对象的任何 属性
或 字段值
。 如果你需要一个类型是线程安全的,或者需要哈希代码在哈希表中能保持不变,那么不可变性很有用。 记录为创建和使用 不可变类型
提供了简洁的语法。
positional record
和 positional readonly record struct
声明 init-only
属性 。 positional record struct
声明 read-write
属性。 可以替代这些默认值中的任何一个,如上个部分中所示。
如果你需要一个以数据为中心的类型是线程安全的,或者需要使哈希表中的哈希代码保持不变,那么不可变性很有用。 但不可变性并不是适用于所有的数据场景。 例如,Entity Framework Core
就 不支持
通过不可变实体类型进行更新。
public record Person(string FirstName, string LastName, string[] PhoneNumbers);public static void Main()
{Person person = new("Nancy", "Davolio", new string[1] { "555-1234" });Console.WriteLine(person.PhoneNumbers[0]); // output: 555-1234person.PhoneNumbers[0] = "555-6789";Console.WriteLine(person.PhoneNumbers[0]); // output: 555-6789
}
init-only
属性无论是通过位置参数(record class
和 readonly record struct
)创建的,还是通过指定 init
访问器创建的,都具有浅的不可变性。 初始化后,将不能更改值型属性的值或引用型属性的引用。 不过,引用型属性引用的数据是可以更改的。 下面的示例展示了引用型不可变属性的内容(本例中是数组)是可变的:
二、记录与类和结构的区别
声明
和 实例化
类 或 结构 时使用的语法与 操作记录
时的 相同
。 只是将 class
关键字替换为 record
,或者使用 record struct
而不是 struct
。 同样地,记录类支持相同的表示 继承
关系的语法。 记录与类的区别如下所示:
- 可在主构造函数中使用位置参数来创建和实例化具有不可变属性的类型。
- 在类中指示引用相等性或不相等的方法和运算符(例如
Object.Equals(Object
) 和==
)在记录中指示值相等性或不相等。 - 可使用
with
表达式对不可变对象创建在所选属性中具有新值的副本。 - 记录的
ToString
方法会创建一个格式字符串,它显示对象的类型名称及其所有公共属性的名称和值。 - 记录可从另一个记录
继承
。 但记录不可从类继承,类也不可从记录继承。
记录结构与结构的不同之处是,编译器合成了方法来确定相等性和 ToString
。 编译器为位置记录结构合成 Deconstruct
方法。
编译器为 record class
中的每个主构造函数参数合成一个公共仅初始化属性。 在 record struct
中,编译器合成公共读写属性。 编译器不会在不包含 record
修饰符的 class
和 struct
类型中创建主构造函数参数的属性。
三、属性定义的位置语法
在创建实例时,可以使用位置参数来声明记录的属性,并初始化属性值:
public record Person(string FirstName, string LastName);public static void Main()
{Person person = new("Nancy", "Davolio");Console.WriteLine(person);// output: Person { FirstName = Nancy, LastName = Davolio }
}
当你为属性定义使用位置语法时,编译器将创建以下内容:
- 记录声明中提供的每个位置参数的公共自动实现属性。
- 对于
record
和readonly record struc
t 类型,为record
属性。 - 对于
record struct
类型,为读写属性。
- 对于
- 主构造函数,它的参数与记录声明上的位置参数匹配。
- 对于
record struct
类型,则是将每个字段设置为其默认值的无参数构造函数。 - 一个
Deconstruct
方法,对记录声明中提供的每个位置参数都有一个out
参数。 此方法解构了使用位置语法定义的属性;它忽略了使用标准属性语法定义的属性。
你可能想要将属性添加到编译器从记录定义中创建的任何元素。 你可以向应用于位置记录属性的任何特性添加目标。 System.Text.Json.Serialization.JsonPropertyNameAttribute 记录的每个属性应用 Person
。 property:
目标指示该特性应用于编译器生成的属性。 其他值包括将该特性应用于字段的 field:
,以及将该特性应用于参数的 param:
。
/// <summary>
/// Person record type
/// </summary>
/// <param name="FirstName">First Name</param>
/// <param name="LastName">Last Name</param>
/// <remarks>
/// The person type is a positional record containing the
/// properties for the first and last name. Those properties
/// map to the JSON elements "firstName" and "lastName" when
/// serialized or deserialized.
/// </remarks>
public record Person([property: JsonPropertyName("firstName")] string FirstName, [property: JsonPropertyName("lastName")] string LastName);
上面的示例还演示了如何为记录创建 XML
文档注释。 你可以添加 <param>
标记,以添加主要构造函数参数的文档。
如果生成的自动生成的属性定义不是所需的属性,则可以定义自己的同名属性。 例如,你可能想要更改可访问性或可变性,或者为 get
或 set
访问器提供实现。 如果在源中声明属性,则必须从记录的位置参数初始化该属性。 如果属性是自动实现的属性,则必须初始化该属性。 如果在源中添加支持字段,则必须初始化支持字段。 生成的析构函数将使用属性定义。 例如,下面的示例声明了位置记录 FirstName
的 LastName
和 public
属性,但将 Id
位置参数限制为 internal
。 可以对记录和 record struct
类型使用此语法。
public record Person(string FirstName, string LastName, string Id)
{internal string Id { get; init; } = Id;
}public static void Main()
{Person person = new("Nancy", "Davolio", "12345");Console.WriteLine(person.FirstName); //output: Nancy}
记录类型不需要声明任何位置属性。 你可以在没有任何位置属性的情况下声明一个记录,也可以声明其他字段和属性,如以下示例中所示:
public record Person(string FirstName, string LastName)
{public string[] PhoneNumbers { get; init; } = [];
};
如果使用标准属性语法来定义属性,但省略了访问修饰符,这些属性将隐式地 private
。
四、 非破坏性变化
如果需要复制包含一些修改的实例,可以使用 with
表达式来实现非破坏性变化。 with
表达式创建一个新的记录实例,该实例是现有记录实例的一个副本,修改了指定属性和字段。 使用对象初始值设定项语法来指定要更改的值,如以下示例中所示:
public record Person(string FirstName, string LastName)
{public string[] PhoneNumbers { get; init; }
}public static void Main()
{Person person1 = new("Nancy", "Davolio") { PhoneNumbers = new string[1] };Console.WriteLine(person1);// output: Person { FirstName = Nancy, LastName = Davolio, PhoneNumbers = System.String[] }Person person2 = person1 with { FirstName = "John" };Console.WriteLine(person2);// output: Person { FirstName = John, LastName = Davolio, PhoneNumbers = System.String[] }Console.WriteLine(person1 == person2); // output: Falseperson2 = person1 with { PhoneNumbers = new string[1] };Console.WriteLine(person2);// output: Person { FirstName = Nancy, LastName = Davolio, PhoneNumbers = System.String[] }Console.WriteLine(person1 == person2); // output: Falseperson2 = person1 with { };Console.WriteLine(person1 == person2); // output: True
}
with
表达式可以设置位置属性或使用标准属性语法创建的属性。 显式声明属性必须有一个 init
或 set
访问器才能在 with
表达式中进行更改。
with
表达式的结果是一个浅的副本,这意味着对于引用属性,只复制对实例的引用。 原始记录和副本最终都具有对同一实例的引用。
为了对 record class
类型实现此功能,编译器合成了一个克隆方法和一个复制构造函数。 虚拟克隆方法返回由复制构造函数初始化的新记录。 当使用 with
表达式时,编译器将创建调用克隆方法的代码,然后设置 with
表达式中指定的属性。
如果你需要不同的复制行为,可以在 record class
中编写自己的复制构造函数。 如果这样做,编译器不会合成方法。 如果记录是 private
,则使构造函数为 sealed
,否则使其为 protected
。 编译器不会针对 record struct
类型合成复制构造函数。 虽然你可以编写一个方法,但编译器不会为 with 表达式生成对它的调用。 record struct
的值在分配时进行复制。
你不能替代克隆方法,也不能在任意记录类型中创建名为 Clone
的成员。 克隆方法的实际名称是由编译器生成的。
五、用于显示的内置格式设置
记录类型具有编译器生成的 ToString
方法,可显示公共属性和字段的名称和值。 ToString
方法返回一个格式如下的字符串:
<record type name> { <property name> = <value>, <property name> = <value>, ...}
为 <value>
打印的字符串是 ToString()
针对属性类型返回的字符串。 在以下示例中,ChildNames
是 System.Array
,其中 ToString
返回 System.String[]
:
Person { FirstName = Nancy, LastName = Davolio, ChildNames = System.String[] }
为了实现此功能,编译器在 record class
类型中合成了一个虚拟 PrintMembers
方法和一个 ToString
替代。 此成员在 record struct
类型中为 private
。 ToString
替代创建了一个 StringBuilder
对象,它的类型名称后跟一个左括号。 它调用 PrintMembers
以添加属性名称和值,然后添加右括号。 下面的示例展示了类似于合成替代中包含的代码:
public override string ToString()
{StringBuilder stringBuilder = new StringBuilder();stringBuilder.Append("Teacher"); // type namestringBuilder.Append(" { ");if (PrintMembers(stringBuilder)){stringBuilder.Append(" ");}stringBuilder.Append("}");return stringBuilder.ToString();
}
你可以提供自己的 PrintMembers
实现或 ToString
替代。 本文后面的派生记录中的 PrintMembers
格式设置一节中提供了示例。 您对 ToString
的实现可能包括 sealed
修饰符,以防止编译器为任何派生记录生成 ToString
实现。 可以在 record
类型的层次结构中创建一致的字符串表示形式。 (派生记录仍会为所有派生属性生成一个 PrintMembers
方法。)
六、继承
本部分仅适用于 record class
类型。
一条记录可以从另一条记录继承。 但是,记录不能从类继承,类也不能从记录继承。
6.1 派生记录类型中的位置参数
派生记录为基本记录主构造函数中的所有参数声明位置参数。 基本记录声明并初始化这些属性。 派生记录不会隐藏它们,而只会创建和初始化未在其基本记录中声明的参数的属性。
下面的示例说明了具有位置属性语法的继承:
public abstract record Person(string FirstName, string LastName);
public record Teacher(string FirstName, string LastName, int Grade): Person(FirstName, LastName);
public static void Main()
{Person teacher = new Teacher("Nancy", "Davolio", 3);Console.WriteLine(teacher);// output: Teacher { FirstName = Nancy, LastName = Davolio, Grade = 3 }
}
6.2 继承层次结构中的相等性
本部分适用于 record class
类型,但不适用于 record struct
类型。 要使两个记录变量相等,运行时类型必须相等。 包含变量的类型可能不同。 下面的代码示例演示了继承的相等性比较:
public abstract record Person(string FirstName, string LastName);
public record Teacher(string FirstName, string LastName, int Grade): Person(FirstName, LastName);
public record Student(string FirstName, string LastName, int Grade): Person(FirstName, LastName);
public static void Main()
{Person teacher = new Teacher("Nancy", "Davolio", 3);Person student = new Student("Nancy", "Davolio", 3);Console.WriteLine(teacher == student); // output: FalseStudent student2 = new Student("Nancy", "Davolio", 3);Console.WriteLine(student2 == student); // output: True
}
在此示例中,所有变量都声明为 Person
,即使该实例是 Student
或 Teacher
的派生类型也是如此。 这些实例都具有相同的属性和相同的属性值。 但 student == teacher
返回 False
(尽管这两个都是 Person
型变量),student == student2
返回 True
(尽管一个是 Person 变量,而另一个是 Student 变量)。 相等性测试依赖于实际对象的运行时类型,而不是声明的变量类型。
为实现此行为,编译器合成了一个 EqualityContract
属性,该属性返回一个与记录类型匹配的 Type
对象。 利用 EqualityContract
相等性方法在检查相等性时,就可以比较对象的运行时类型。 如果记录的基类型为 object
,则此属性为 virtual
。 如果基类型是其他记录类型,则此属性是一个替代。 如果记录类型为 sealed
,则此属性实际上是 sealed
,因为类型是 sealed
。
在代码比较派生类型的两个实例时,合成的相等性方法会检查基类型和派生类型的所有数据成员是否相等。 合成的 GetHashCode
方法从基类型和派生的记录类型中声明的所有数据成员中使用 GetHashCode
方法。 包含所有声明字段的数据成员 record
,以及任何自动实现的属性的编译器合成后盾字段。
6.3 派生记录中的 with 表达式
with
表达式结果的运行时间类型与表达式操作数相同: 运行时类型的所有属性都会被复制,但你只能设置编译时类型的属性,如下面的示例所示:
public record Point(int X, int Y)
{public int Zbase { get; set; }
};
public record NamedPoint(string Name, int X, int Y) : Point(X, Y)
{public int Zderived { get; set; }
};public static void Main()
{Point p1 = new NamedPoint("A", 1, 2) { Zbase = 3, Zderived = 4 };Point p2 = p1 with { X = 5, Y = 6, Zbase = 7 }; // Can't set Name or ZderivedConsole.WriteLine(p2 is NamedPoint); // output: TrueConsole.WriteLine(p2);// output: NamedPoint { X = 5, Y = 6, Zbase = 7, Name = A, Zderived = 4 }Point p3 = (NamedPoint)p1 with { Name = "B", X = 5, Y = 6, Zbase = 7, Zderived = 8 };Console.WriteLine(p3);// output: NamedPoint { X = 5, Y = 6, Zbase = 7, Name = B, Zderived = 8 }
}
6.4 派生记录中的 PrintMembers 格式设置
派生记录类型的合成 PrintMembers
方法调用基实现。 结果是派生类型和基类型的所有公共属性和字段都包含在 ToString
输出中,如以下示例中所示:
public abstract record Person(string FirstName, string LastName);
public record Teacher(string FirstName, string LastName, int Grade): Person(FirstName, LastName);
public record Student(string FirstName, string LastName, int Grade): Person(FirstName, LastName);public static void Main()
{Person teacher = new Teacher("Nancy", "Davolio", 3);Console.WriteLine(teacher);// output: Teacher { FirstName = Nancy, LastName = Davolio, Grade = 3 }
}
你可以提供自己的 PrintMembers
方法的实现。 如果这样做,请使用以下签名:
- 对于派生自
sealed
的object
记录(不声明基本记录):使用 private bool PrintMembers(StringBuilder builder); - 对于从另一个记录派生的
sealed
记录(注意封闭类型是sealed
,因此该方法实际上是 sealed):protected override bool PrintMembers(StringBuilder builder); - 对于非
sealed
且派生自对象的记录:使用 protected virtual bool PrintMembers(StringBuilder builder); - 对于非
sealed
且派生自其他记录的记录:使用 protected override bool PrintMembers(StringBuilder builder);
下面的代码示例替换了合成的 PrintMembers
方法,一个是派生自对象的记录类型,另一个是派生自另一条记录的记录类型:
public abstract record Person(string FirstName, string LastName, string[] PhoneNumbers)
{protected virtual bool PrintMembers(StringBuilder stringBuilder){stringBuilder.Append($"FirstName = {FirstName}, LastName = {LastName}, ");stringBuilder.Append($"PhoneNumber1 = {PhoneNumbers[0]}, PhoneNumber2 = {PhoneNumbers[1]}");return true;}
}public record Teacher(string FirstName, string LastName, string[] PhoneNumbers, int Grade): Person(FirstName, LastName, PhoneNumbers)
{protected override bool PrintMembers(StringBuilder stringBuilder){if (base.PrintMembers(stringBuilder)){stringBuilder.Append(", ");};stringBuilder.Append($"Grade = {Grade}");return true;}
};public static void Main()
{Person teacher = new Teacher("Nancy", "Davolio", new string[2] { "555-1234", "555-6789" }, 3);Console.WriteLine(teacher);// output: Teacher { FirstName = Nancy, LastName = Davolio, PhoneNumber1 = 555-1234, PhoneNumber2 = 555-6789, Grade = 3 }
}
即使基记录密封了 ToString 方法,编译器也会在派生记录中合成 PrintMembers。 还可以创建自己的 PrintMembers 实现。
6.5 派生记录中的解构函数行为
派生记录的 Deconstruct
方法返回编译时类型所有位置属性的值。 如果变量类型为基本记录,则只解构基本记录属性,除非该对象强制转换为派生类型。 下面的示例演示了如何对派生记录调用解构函数。
public abstract record Person(string FirstName, string LastName);
public record Teacher(string FirstName, string LastName, int Grade): Person(FirstName, LastName);
public record Student(string FirstName, string LastName, int Grade): Person(FirstName, LastName);public static void Main()
{Person teacher = new Teacher("Nancy", "Davolio", 3);var (firstName, lastName) = teacher; // Doesn't deconstruct GradeConsole.WriteLine($"{firstName}, {lastName}");// output: Nancy, Davoliovar (fName, lName, grade) = (Teacher)teacher;Console.WriteLine($"{fName}, {lName}, {grade}");// output: Nancy, Davolio, 3
}
七、泛型约束
record
关键字是 class
或 struct
类型的修饰符。 添加 record
修饰符包括本文前面所述的行为。 没有任何泛型约束要求类型是记录。 record class
满足 class
约束。 record struct
满足 struct
约束。 有关详细信息,请参阅类型参数的约束。
🎀🎀🎀代码之美系列目录🎀🎀🎀
一、C# 命名规则规范
二、C# 代码约定规范
三、C# 参数类型约束
四、浅析 B/S 应用程序体系结构原则
五、浅析 C# Async 和 Await
六、浅析 ASP.NET Core SignalR 双工通信
七、浅析 ASP.NET Core 和 MongoDB 创建 Web API
八、浅析 ASP.NET Web UI 框架 Razor Pages/MVC/Web API/Blazor
九、如何使用 MiniProfiler WebAPI 分析工具
十、浅析 .NET Core 中各种 Filter
十一、C#.Net筑基-类型系统
十二、C#.Net 筑基-运算符
十三、C#.Net筑基-解密委托与事件
十四、C#.Net筑基-集合知识大全
十五、C#.Net筑基 - 常见类型
十六、C#.NET体系图文概述—2024最全总结
十七、C# 强大无匹的模式匹配,让代码更加优雅
相关文章:

C# 中的记录类型简介 【代码之美系列】
🎀🎀🎀代码之美系列目录🎀🎀🎀 一、C# 命名规则规范 二、C# 代码约定规范 三、C# 参数类型约束 四、浅析 B/S 应用程序体系结构原则 五、浅析 C# Async 和 Await 六、浅析 ASP.NET Core SignalR 双工通信 …...

利用Java爬虫速卖通按关键字搜索AliExpress商品
在这个信息爆炸的时代,数据的价值日益凸显。对于电商领域的从业者来说,能够快速获取商品信息成为了一项重要的技能。速卖通(AliExpress)作为全球领先的跨境电商平台,拥有海量的商品数据。本文将介绍如何使用Java语言编…...
gitlab runner 实现 微信小程序自动化部署
微信小程序多人开发的情况下,开发人员都只能在本机上发布体验版,且需要到小程序管理后台自行切换到自己发布的版本,会出现体验版本覆盖的问题。给开发测试带来问题。 miniprogram-ci 的发布,使得开发人员可以通过命令行上传小程序…...
Playwright爬虫xpath获取技巧
示例一 <button class"MuiButtonBase-root MuiButton-root MuiLoadingButton-root MuiButton-contained MuiButton-containedPrimary MuiButton-sizeLarge MuiButton-containedSizeLarge MuiButton-colorPrimary MuiButton-fullWidth MuiButton-root MuiLoadingButton…...

总结TCP/IP四层模型
总结TCP/IP四层模型 阅读目录(Content) 一、TCP/IP参考模型概述 1.1、TCP/IP参考模型的层次结构二、TCP/IP四层功能概述 2.1、主机到网络层 2.2、网络互连层 2.3、传输层 2.3、应用层 三、TCP/IP报文格式 3.1、IP报文格式3.2、TCP数据段格式3.3、UDP数据段格式3.4、套…...
netcat和nmap的区别
Netcat 和 Nmap 是两种广泛使用的网络工具,但它们的功能和使用场景有所不同。下面是这两种工具的对比: Netcat(nc) 用途和功能: 网络连接: Netcat 是一个功能强大的网络工具,用于创建 TCP 或 UDP 连接。可以用来进行网…...
MinIO服务器文件复制(Windows环境Linux环境)
一、下载 Windows环境:https://dl.min.io/server/minio/release/windows-amd64/minio.exe Linux环境: > curl https://dl.min.io/client/mc/release/linux-amd64/mc \ --create-dirs \ -o $HOME/minio/mc > chmod x $HOME/minio/mc > expo…...

【机器学习】【朴素贝叶斯分类器】从理论到实践:朴素贝叶斯分类器在垃圾短信过滤中的应用
🌟 关于我 🌟 大家好呀!👋 我是一名大三在读学生,目前对人工智能领域充满了浓厚的兴趣,尤其是机器学习、深度学习和自然语言处理这些酷炫的技术!🤖💻 平时我喜欢动手做实…...
无监督学习算法
K-均值聚类(K-means clustering)是一种常用的无监督学习算法,用于将数据集划分成 K 个不同的组或簇。该算法主要通过计算数据点之间的欧几里得距离来确定数据点之间的相似性,并根据相似性将数据点分配到不同的簇中,使得…...

【Compose multiplatform教程17】【组件】BoxWithConstraints组件
查看全部组件 https://blog.csdn.net/b275518834/article/details/144751353 BoxWithConstraints 功能说明:它是 Jetpack Compose 中的关键布局组件,能够精准捕捉自身所在容器的尺寸约束信息,通过获取最大宽度和最大高度这两个关键属性&…...

银河麒麟操作系统安装达梦数据库(超详细)
目录 引言1. 前期准备1.1 安装麒麟系统1.2 下载达梦数据库安装包(DM8)1.3 上传安装包到麒麟系统1.4 挂载安装包(iso)文件1.5 配置安装用户和组1.6 创建安装路径及修改权限1.7 设置临时安装目录 2. 安装达梦数据库(DM8&…...

Spring源码_05_IOC容器启动细节
前面几章,大致讲了Spring的IOC容器的大致过程和原理,以及重要的容器和beanFactory的继承关系,为后续这些细节挖掘提供一点理解基础。掌握总体脉络是必要的,接下来的每一章都是从总体脉络中, 去研究之前没看的一些重要…...

科大讯飞在线语音合成(流式版)python版
1、进入自己的项目 复制APPID、APISecret、APIKey 2、添加好听发音人 复制vcn参数 3、需要替换代码部分: 换自己喜欢的发声人的参数 换上自己的APPID、APISecret、APIKey 4、完整代码: # -*- coding:utf-8 -*- import _thread as thread import base…...
常见搜索算法汇总
常见搜索算法总结 搜索算法是人工智能和计算机科学中用于解决问题、优化路径或发现数据模式的关键技术。本文将对常见的搜索算法进行总结,包括A*算法、D*算法、模拟退火(Simulated Annealing)、爬山法(Hill Climbing)、…...
vue 中 ref 详解
一、定义与基本用法 1. 定义 在 Vue.js 中,ref是一个用于在组件中获取 DOM 元素或者子组件实例引用的属性。它提供了一种直接访问元素或组件的方式,使得我们可以在 JavaScript 代码中对它们进行操作。 2. 基本使用 在模板中,可以通过给元…...
探索开源项目 kernel:技术的基石与无限可能
在开源的广袤世界中,有一颗璀璨的明星——kernel(https://gitee.com/openeuler/kernel),它宛如一座技术的宝藏,蕴含着无数的智慧与创新,为众多开发者所瞩目和敬仰。 一、初窥 kernel 项目 当我第一次接触…...

C 实现植物大战僵尸(二)
C 实现植物大战僵尸(二) 前文链接,C 实现植物大战僵尸(一) 五 制作启动菜单 启动菜单函数 void startUI() {IMAGE imageBg, imgMenu1, imgMenu2;loadimage(&imageBg, "res/menu.png");loadimage(&am…...

Vivado - TCL 命令(DPU脚本、v++命令、impl策略)
目录 1. 简介 2. TCL 示例 2.1 DPU TCL 脚本 2.1.1 源码-精简 2.1.2 依赖关系 2.1.3 查 v 步骤列表 2.1.4 生成 DPU.XO 2.2 CPU 示例 2.2.1 源码-框架 2.2.2 示例设计详解 2.3 创建运行脚本 2.3.1 Generate scripts 2.3.2 runme.sh 文件 2.3.3 design_1_wrapper…...

【JDBC】数据库连接的艺术:深入解析数据库连接池、Apache-DBUtils与BasicDAO
文章目录 前言🌍 一.连接池❄️1. 传统获取Conntion问题分析❄️2. 数据库连接池❄️3.连接池之C3P0技术🍁3.1关键特性🍁3.2配置选项🍁3.3使用示例 ❄️4. 连接池之Druid技术🍁 4.1主要特性🍁 4.2 配置选项…...
hadoop-common的下载位置分享
1.GitHub - steveloughran/winutils: Windows binaries for Hadoop versions (built from the git commit ID used for the ASF relase) 2.GitHub - cdarlint/winutils: winutils.exe hadoop.dll and hdfs.dll binaries for hadoop windows 3.winutils: hadoop winutils 镜像...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...

label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...

python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...

Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...

JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...

脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...
comfyui 工作流中 图生视频 如何增加视频的长度到5秒
comfyUI 工作流怎么可以生成更长的视频。除了硬件显存要求之外还有别的方法吗? 在ComfyUI中实现图生视频并延长到5秒,需要结合多个扩展和技巧。以下是完整解决方案: 核心工作流配置(24fps下5秒120帧) #mermaid-svg-yP…...