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

网站定制合同/网站备案查询官网

网站定制合同,网站备案查询官网,用自己电脑做网站服务器-phpstudy+花生壳,网站整套模板项目代码下载一、引言:记录类型的神奇登场 在 C# 的编程世界中,数据结构就像是构建软件大厦的基石,其重要性不言而喻。然而,传统的数据结构定义方式,尤其是在处理简单的数据承载对象时,常常显得繁琐复杂。例如&#xf…

一、引言:记录类型的神奇登场

在 C# 的编程世界中,数据结构就像是构建软件大厦的基石,其重要性不言而喻。然而,传统的数据结构定义方式,尤其是在处理简单的数据承载对象时,常常显得繁琐复杂。例如,当我们需要定义一个表示人员信息的类时,通常需要编写如下代码:

public class Person
{public string Name { get; set; }public int Age { get; set; }public Person(string name, int age){Name = name;Age = age;}
}

上述代码中,我们不仅要定义属性,还要编写构造函数来初始化这些属性。当项目中存在大量类似这样简单的数据结构时,代码量会迅速膨胀,可读性和维护性也会随之降低。

而 C# 9.0 带来的记录类型(Record Types),就像是一把神奇的钥匙,为我们打开了简化数据结构定义的大门。记录类型能够以一种简洁明了的方式定义数据结构,让代码变得更加优雅和高效。例如,使用记录类型来定义上述的Person结构,只需一行代码:

public record Person(string Name, int age);

仅仅这一行代码,就完成了属性定义、构造函数生成等一系列操作,极大地简化了开发流程。记录类型不仅能减少代码的编写量,还在相等性比较、对象克隆等方面提供了便捷的功能,让开发效率得到显著提升。接下来,就让我们深入探索 C# 9.0 记录类型的奥秘,看看它是如何施展这简化数据结构的 5 步魔法的吧。

二、第一步:极简定义,告别冗长构造

在 C# 传统的类定义方式中,当我们需要创建一个简单的数据结构类时,往往需要编写较多的代码。以定义一个表示学生信息的类Student为例,传统方式如下:

public class Student
{public string Name { get; set; }public int Age { get; set; }public string Major { get; set; }public Student(string name, int age, string major){Name = name;Age = age;Major = major;}
}

在这段代码中,我们不仅要定义Name、Age和Major这三个属性,还要编写构造函数来初始化这些属性。如果项目中有大量类似这样简单的数据结构类,代码量会显著增加,而且这些重复的代码会降低代码的可读性和维护性。

而在 C# 9.0 中,使用记录类型来定义相同的Student数据结构,代码变得极其简洁:

public record Student(string Name, int Age, string Major);

仅仅这一行代码,就完成了属性定义、构造函数生成等一系列操作。编译器会自动为这个记录类型生成一个构造函数,该构造函数接受Name、Age和Major作为参数,用于初始化相应的属性。不仅如此,记录类型还会自动生成ToString、Equals和GetHashCode等方法,这些方法都是基于记录类型的属性值来实现的。

例如,当我们创建Student记录类型的实例时,可以这样使用:

var student1 = new Student("Alice", 20, "Computer Science");
Console.WriteLine(student1);

上述代码创建了一个student1实例,并使用Console.WriteLine输出该实例。由于记录类型自动生成了ToString方法,所以输出结果会以一种易读的格式展示student1的属性值,大致如下:

Student { Name = Alice, Age = 20, Major = Computer Science }

通过对比传统类和记录类型的定义方式,我们可以明显看出记录类型在简化数据结构定义方面的强大优势。它减少了大量的样板代码,让开发者能够更专注于业务逻辑的实现,提高了开发效率 。

三、第二步:轻松克隆,“with” 关键字显神通

在传统的 C# 编程中,当我们需要克隆一个对象并对其属性进行修改时,往往需要编写较为繁琐的代码。例如,对于前面定义的Student类,如果要克隆一个Student对象并修改其年龄,可能需要这样实现:

public class Student
{public string Name { get; set; }public int Age { get; set; }public string Major { get; set; }public Student(string name, int age, string major){Name = name;Age = age;Major = major;}// 手动实现克隆方法public Student Clone(){return new Student(Name, Age, Major);}
}// 使用克隆方法并修改属性
var student1 = new Student("Bob", 21, "Mathematics");
var student2 = student1.Clone();
student2.Age = 22;

在上述代码中,我们不仅要手动编写Clone方法来实现对象的克隆,而且代码看起来比较冗长和繁琐。

而在 C# 9.0 的记录类型中,使用with关键字可以轻松地实现对象的克隆并修改属性。with关键字就像是一个神奇的 “复制修改器”,它会创建一个基于现有记录对象的副本,并且可以在创建副本的同时修改指定的属性值,而其他未指定修改的属性则保持不变 。这一特性不仅大大简化了代码,还保障了对象的不变性原则,即原始对象不会被修改,而是生成一个新的对象来承载修改后的状态。

还是以Student记录类型为例,使用with关键字进行对象克隆和属性修改的代码如下:

public record Student(string Name, int Age, string Major);// 使用with关键字克隆并修改属性
var student1 = new Student("Charlie", 22, "Physics");
var student3 = student1 with { Age = 23 };

在上述代码中,student1 with { Age = 23 }这行代码创建了一个student1的副本student3,并且将student3的Age属性修改为 23,而Name和Major属性则与student1保持一致。

如果Student记录类型中的属性使用了init访问器来实现不可变,with关键字同样适用,并且能更好地体现不可变对象的优势。例如:

public record Student(string Name, int Age, string Major)
{public string Name { get; init; } = Name;public int Age { get; init; } = Age;public string Major { get; init; } = Major;
};var student1 = new Student("David", 23, "Chemistry");
var student4 = student1 with { Age = 24 };

在这个例子中,Student记录类型的属性是不可变的,通过with关键字创建新对象并修改属性,既保证了数据的不可变性,又实现了灵活的数据更新。

通过对比可以看出,with关键字在记录类型中实现对象克隆和属性修改的操作上,比传统的类方式更加简洁、直观,大大提高了开发效率 。

四、第三步:智能相等,告别 equals 的烦恼

在传统的 C# 编程中,当我们需要判断两个对象是否相等时,往往需要手动重写Equals和GetHashCode方法。以之前定义的Student类为例,如果要实现基于属性值的相等性比较,代码如下:

public class Student
{public string Name { get; set; }public int Age { get; set; }public string Major { get; set; }public Student(string name, int age, string major){Name = name;Age = age;Major = major;}public override bool Equals(object obj){if (obj == null || GetType()!= obj.GetType()){return false;}Student other = (Student)obj;return Name == other.Name && Age == other.Age && Major == other.Major;}public override int GetHashCode(){return HashCode.Combine(Name, Age, Major);}
}

在上述代码中,我们需要手动编写Equals方法来比较两个Student对象的属性值是否相等,同时还需要编写GetHashCode方法来生成哈希码,以确保相等的对象具有相同的哈希码 。这不仅增加了代码的编写量,还容易出现错误。

而在 C# 9.0 的记录类型中,编译器会自动为记录类型生成基于属性值的相等性比较逻辑,包括Equals和GetHashCode方法 。这意味着我们无需手动重写这些方法,就可以直接使用==运算符或Equals方法来判断两个记录类型的实例是否相等。

例如,对于之前定义的Student记录类型:

public record Student(string Name, int Age, string Major);

我们可以这样进行相等性比较:

var student1 = new Student("Eve", 23, "Biology");
var student2 = new Student("Eve", 23, "Biology");
var student3 = new Student("Frank", 24, "Economics");Console.WriteLine(student1 == student2); // 输出True
Console.WriteLine(student1.Equals(student2)); // 输出True
Console.WriteLine(student1 == student3); // 输出False

在上述代码中,student1和student2具有相同的属性值,所以student1 == student2和student1.Equals(student2)都返回True;而student1和student3的属性值不同,所以student1 == student3返回False。

记录类型的这种自动相等性比较功能,在处理集合中的数据比较、去重等操作时非常有用。例如,在一个包含Student记录类型的集合中,判断两个Student是否相等时,直接使用==运算符即可:

var studentList = new List<Student>
{new Student("Grace", 22, "History"),new Student("Hank", 21, "Geography")
};var newStudent = new Student("Grace", 22, "History");
bool isExists = studentList.Any(s => s == newStudent);
Console.WriteLine(isExists); // 输出True

上述代码中,studentList.Any(s => s == newStudent)用于判断studentList集合中是否存在与newStudent相等的元素,由于记录类型的自动相等性比较功能,我们可以非常方便地实现这一操作。

通过对比可以看出,C# 9.0 记录类型的自动相等性比较功能,大大简化了代码,减少了开发人员的工作量,提高了开发效率 。

五、第四步:深度剖析,记录类型的魔法内幕

前面我们已经体验到了 C# 9.0 记录类型在简化数据结构定义、对象克隆和相等性比较方面的强大功能。接下来,让我们深入记录类型的内部,探索它背后的魔法机制,看看编译器是如何施展这些神奇的操作的。

编译器的魔法合成

当我们使用记录类型定义一个数据结构时,编译器会自动为我们合成一系列非常有用的方法 。以之前定义的Student记录类型为例:

public record Student(string Name, int Age, string Major);

编译器会为这个记录类型合成以下方法:

  1. 构造函数:编译器会生成一个主构造函数,其参数与记录类型定义时的属性参数一致。例如,对于上述Student记录类型,生成的构造函数类似于:
public Student(string Name, int Age, string Major)
{this.Name = Name;this.Age = Age;this.Major = Major;
}

这个构造函数用于初始化记录类型的属性。此外,编译器还会生成一个受保护的复制构造函数(如果记录类型不是密封的),用于创建记录的副本。例如:

protected Student(Student other)
{this.Name = other.Name;this.Age = other.Age;this.Major = other.Major;
}
  1. 相等性比较方法:记录类型会自动实现基于属性值的相等性比较,编译器会合成Equals和GetHashCode方法。Equals方法用于比较两个记录类型的实例是否相等,它会比较两个实例的所有属性值。例如:
public override bool Equals(object obj)
{if (obj == null || GetType()!= obj.GetType()){return false;}Student other = (Student)obj;return Name == other.Name && Age == other.Age && Major == other.Major;
}public override int GetHashCode()
{return HashCode.Combine(Name, Age, Major);
}

GetHashCode方法用于生成记录类型实例的哈希码,它会根据记录类型的所有属性值生成一个唯一的哈希码,以确保相等的对象具有相同的哈希码 。

\3. ToString 方法:编译器会合成一个ToString方法,用于返回记录类型实例的字符串表示形式。这个字符串表示形式会包含记录类型的所有属性名和属性值,以一种易读的格式展示。例如:

public override string ToString()
{return $"Student {{ Name = {Name}, Age = {Age}, Major = {Major} }}";
}
  1. 克隆方法:虽然我们在代码中看不到名为Clone的方法,但编译器会生成一个用于创建记录副本的方法。这个方法实际上是使用with表达式来实现的,它会创建一个新的记录实例,并将原始记录的属性值复制到新实例中,同时可以根据需要修改指定的属性值。例如,对于Student记录类型,编译器生成的克隆方法类似于:
public Student Clone()
{return this with { };
}
  1. Deconstruct 方法:对于位置记录(即使用简洁语法定义的记录类型,如public record Student(string Name, int Age, string Major);),编译器还会生成一个Deconstruct方法,用于将记录类型的实例解构为其组件属性。例如:
public void Deconstruct(out string Name, out int Age, out string Major)
{Name = this.Name;Age = this.Age;Major = this.Major;
}

这个Deconstruct方法可以方便地将记录类型的实例分解为多个变量,例如:

var student = new Student("Ivy", 24, "Psychology");
var (name, age, major) = student;
Console.WriteLine($"Name: {name}, Age: {age}, Major: {major}");

初始化逻辑与不可变性

记录类型的属性默认是不可变的,这是通过使用init访问器来实现的。例如,对于Student记录类型,其属性的定义实际上类似于:

public record Student
{public string Name { get; init; }public int Age { get; init; }public string Major { get; init; }public Student(string Name, int Age, string Major){this.Name = Name;this.Age = Age;this.Major = Major;}
}

使用init访问器意味着属性只能在对象初始化时被赋值,一旦对象创建完成,属性值就不能被修改。这种不可变性有助于确保数据的一致性和安全性,特别是在多线程环境中,不可变的数据结构可以避免数据竞争和不一致的问题 。

当我们使用new关键字创建记录类型的实例时,会调用编译器生成的构造函数来初始化属性。例如:

var student = new Student("Jack", 25, "Sociology");

在这个过程中,Name、Age和Major属性会被初始化为指定的值,并且之后不能被修改。如果尝试修改属性值,例如:

student.Age = 26; // 编译错误,因为Age属性是不可变的

编译器会报错,提示属性是只读的,无法进行修改。

模式匹配的支持

记录类型对模式匹配提供了很好的支持,这使得我们可以根据记录类型的结构和属性值来进行灵活的条件判断和处理。模式匹配是一种检查数据结构的方式,它允许我们根据数据的特定模式来执行不同的代码分支。在 C# 中,模式匹配最常见的形式是switch表达式。

以Student记录类型为例,我们可以使用模式匹配来根据学生的年龄进行不同的处理:

var student = new Student("Kathy", 22, "Engineering");
switch (student)
{case { Age: < 20 }:Console.WriteLine("This student is relatively young.");break;case { Age: >= 20 and < 25 }:Console.WriteLine("This student is in a typical college age range.");break;case { Age: >= 25 }:Console.WriteLine("This student may be a mature learner.");break;
}

在上述代码中,switch表达式根据student的Age属性值进行匹配,不同的模式对应不同的处理逻辑。这种方式使得代码更加简洁、直观,避免了繁琐的条件判断和类型转换 。

记录类型还支持在模式匹配中使用with表达式来创建临时的记录副本并进行匹配。例如:

var student = new Student("Leo", 23, "Business");
switch (student)
{case { Name: "Leo", Age: var age } with { Major: "Business" }:Console.WriteLine($"Leo is a business student and his age is {age}.");break;
}

在这个例子中,通过with表达式在模式匹配中创建了一个临时的记录副本,并且只关注Name为"Leo"、Age为任意值且Major为"Business"的情况,进一步展示了记录类型在模式匹配中的灵活性和强大功能。

通过深入了解记录类型的内部机制,我们不仅知其然,还知其所以然,这将帮助我们更好地运用记录类型,编写出更加高效、优雅的代码 。

六、第五步:实际应用,记录类型大展身手

前面我们已经深入了解了 C# 9.0 记录类型的各种特性和内部机制,那么在实际的项目开发中,记录类型又能在哪些场景中发挥其强大的作用呢?下面我们将通过几个常见的应用场景来展示记录类型的实际优势。

数据传输对象(DTO)

在现代软件开发中,尤其是在分布式系统和 Web 应用程序中,数据传输对象(DTO)是一种常用的设计模式 。DTO 主要用于在不同的层(如表示层、业务逻辑层和数据访问层)之间传输数据,它通常只包含数据属性,不包含业务逻辑。

在传统的开发中,我们通常使用类来定义 DTO,例如:

public class UserDTO
{public string Username { get; set; }public string Email { get; set; }public int Age { get; set; }public UserDTO(string username, string email, int age){Username = username;Email = email;Age = age;}
}

使用类来定义 DTO 需要编写较多的样板代码,包括属性定义、构造函数等。而且,在比较两个UserDTO对象是否相等时,还需要手动重写Equals和GetHashCode方法。

而使用 C# 9.0 的记录类型来定义UserDTO,代码会变得非常简洁:

public record UserDTO(string Username, string Email, int Age);

仅仅这一行代码,就完成了属性定义、构造函数生成以及相等性比较方法的实现。在数据传输过程中,我们可以方便地创建UserDTO的实例并进行数据传递。例如,在ASP.NET Core Web API 中,我们可以将UserDTO作为控制器方法的返回类型或参数类型:

[ApiController]
[Route("[controller]")]
public class UserController : ControllerBase
{[HttpGet("{id}")]public UserDTO GetUser(int id){// 从数据库或其他数据源获取用户数据var user = new UserDTO("JohnDoe", "johndoe@example.com", 30);return user;}[HttpPost]public IActionResult CreateUser(UserDTO userDTO){// 处理创建用户的逻辑return Ok();}
}

由于记录类型的属性默认是不可变的,这符合 DTO 在数据传输过程中只传递数据而不修改数据的特性,保证了数据的一致性和安全性 。同时,记录类型的自动相等性比较功能在处理 DTO 的比较和去重等操作时也非常方便,减少了开发人员的工作量。

领域模型

在领域驱动设计(DDD)中,领域模型是对业务领域的抽象表示,它包含了业务规则和业务逻辑 。在领域模型中,有一些对象通常被称为值对象,它们主要用于表示一些具有特定业务含义的数据,例如货币金额、日期范围等。值对象的特点是它们的相等性是基于其属性值的,而不是基于对象的引用。

在传统的 C# 开发中,我们通常使用类来定义值对象,并手动实现基于属性值的相等性比较方法。例如,定义一个表示货币金额的值对象Money:

public class Money
{public decimal Amount { get; }public string Currency { get; }public Money(decimal amount, string currency){Amount = amount;Currency = currency;}public override bool Equals(object obj){if (obj == null || GetType()!= obj.GetType()){return false;}Money other = (Money)obj;return Amount == other.Amount && Currency == other.Currency;}public override int GetHashCode(){return HashCode.Combine(Amount, Currency);}
}

上述代码中,我们不仅要定义属性和构造函数,还要手动重写Equals和GetHashCode方法来实现基于属性值的相等性比较。

而使用 C# 9.0 的记录类型来定义Money值对象,代码会变得更加简洁:

public record Money(decimal Amount, string Currency);

记录类型会自动为Money生成基于属性值的相等性比较方法,这使得在领域模型中处理值对象时更加方便和高效。例如,在进行业务逻辑处理时,我们可以直接比较两个Money对象是否相等:

var money1 = new Money(100.0m, "USD");
var money2 = new Money(100.0m, "USD");
if (money1 == money2)
{// 处理相等的业务逻辑
}

此外,记录类型的不可变性也符合值对象的特性,即值对象一旦创建,其属性值就不应该被修改。这有助于确保领域模型的一致性和正确性。

配置对象

在应用程序中,配置对象用于存储应用程序的配置信息,例如数据库连接字符串、日志级别等。配置信息在应用程序运行期间通常是固定不变的,因此使用不可变的数据结构来表示配置对象是一个很好的选择。

在传统的 C# 开发中,我们可以使用类来定义配置对象,并通过将属性设置为只读来实现不可变性。例如:

public class AppConfig
{public string ConnectionString { get; }public string LogLevel { get; }public AppConfig(string connectionString, string logLevel){ConnectionString = connectionString;LogLevel = logLevel;}
}

使用类来定义配置对象需要手动编写构造函数和属性定义,并且在比较两个配置对象是否相等时也需要手动实现相等性比较方法。

而使用 C# 9.0 的记录类型来定义AppConfig配置对象,代码会更加简洁:

public record AppConfig(string ConnectionString, string LogLevel);

记录类型的自动相等性比较和不可变性特性使得配置对象的定义和使用更加方便和安全。例如,在读取配置文件并创建配置对象时,我们可以这样使用:

var config = new AppConfig("Server=localhost;Database=MyDB;User=sa;Password=password", "Info");

在应用程序中,我们可以方便地比较不同的配置对象是否相等,以确保配置的一致性。例如:

var config1 = new AppConfig("Server=localhost;Database=MyDB;User=sa;Password=password", "Info");
var config2 = new AppConfig("Server=localhost;Database=MyDB;User=sa;Password=password", "Info");
if (config1 == config2)
{// 配置相同,继续执行应用程序
}

通过以上几个实际应用场景的展示,我们可以看到 C# 9.0 的记录类型在简化数据结构定义、提高代码可读性和开发效率方面具有显著的优势。无论是在数据传输对象、领域模型还是配置对象等场景中,记录类型都能够发挥其强大的功能,帮助我们编写出更加优雅、高效的代码 。

七、总结:记录类型带来的变革与展望

C# 9.0 的记录类型无疑为我们的编程世界带来了一场意义深远的变革,它以简洁高效的特性,重塑了我们定义和操作数据结构的方式。

从定义的简洁性来看,记录类型告别了传统类定义中冗长的构造函数和繁琐的样板代码,只需一行代码就能轻松定义一个包含多个属性的数据结构,大大减少了开发过程中的重复劳动,让代码更加简洁易读。在对象克隆方面,with关键字的引入堪称神来之笔,它使得对象的克隆和属性修改变得轻而易举,不仅简化了代码逻辑,还遵循了不可变对象的设计原则,提高了代码的安全性和可维护性。而自动实现的基于属性值的相等性比较功能,更是解决了传统开发中手动重写Equals和GetHashCode方法的烦恼,让相等性判断变得直观而准确,在集合操作、数据去重等场景中发挥了巨大的作用 。

在实际应用中,记录类型在数据传输对象(DTO)、领域模型、配置对象等多个场景中都展现出了强大的优势,它能够帮助我们编写出更加优雅、高效的代码,提升项目的整体质量和开发效率。

对于广大开发者而言,C# 9.0 记录类型是一个不可多得的强大工具。我强烈建议大家在今后的项目开发中积极尝试使用记录类型,尤其是在处理那些简单的数据承载对象和需要强调不可变性的数据结构时,记录类型将为你带来意想不到的便利和效率提升。

展望未来,随着 C# 语言的不断发展和演进,我们有理由相信记录类型也将不断完善和增强。未来的版本中,记录类型可能会在性能优化、与其他语言特性的融合等方面取得更大的突破,为开发者提供更加丰富和强大的功能。让我们拭目以待,继续探索 C# 记录类型的无限可能,在编程的道路上不断前行 。

相关文章:

C# 9.0记录类型:解锁开发效率的魔法密码

一、引言&#xff1a;记录类型的神奇登场 在 C# 的编程世界中&#xff0c;数据结构就像是构建软件大厦的基石&#xff0c;其重要性不言而喻。然而&#xff0c;传统的数据结构定义方式&#xff0c;尤其是在处理简单的数据承载对象时&#xff0c;常常显得繁琐复杂。例如&#xf…...

搭建自己的专属AI——使用Ollama+AnythingLLM+Python实现DeepSeek本地部署

前言 最近DeepSeek模型非常火&#xff0c;其通过对大模型的蒸馏得到的小模型可以较轻松地在个人电脑上运行&#xff0c;这也使得我们有机会在本地构建一个专属于自己的AI&#xff0c;进而把AI“调教”为我们希望的样子。本篇文章中我将介绍如何使用OllamaAnythingLLMPython实现…...

『 C++ 』中理解回调类型在 C++ 中的使用方式。

文章目录 案例 1&#xff1a;图形绘制库中的回调使用场景说明代码实现代码解释 案例 2&#xff1a;网络服务器中的连接和消息处理回调场景说明代码实现代码解释 案例 3&#xff1a;定时器中的回调使用场景说明代码实现代码解释 以下将通过不同场景给出几个使用回调类型的具体案…...

git多人协作

目录 一、项目克隆 二、 1、进入克隆仓库设置 2、协作处理 3、冲突处理 4、多人协作分支的推送拉取删除 1、分支推送&#xff08;2种&#xff09; 2、远程分支拉取&#xff08;2种&#xff09; 3、远程分支删除 一、项目克隆 git clone 画船听雨眠/test1 (自定义的名…...

CTFSHOW-WEB入门-命令执行71-77

题目&#xff1a;web 71 题目&#xff1a;解题思路&#xff1a;分析可知highlight_file() 函数被禁了&#xff0c;先想办法看看根目录&#xff1a;cvar_export(scandir(dirname(‘/’))); 尝试一下发现很惊奇&#xff1a;&#xff08;全是&#xff1f;&#xff09;这种情况我也…...

浅谈《图解HTTP》

感悟 滑至尾页的那一刻&#xff0c;内心突兀的涌来一阵畅快的感觉。如果说从前对互联网只是懵懵懂懂&#xff0c;但此刻却觉得她是如此清晰而可爱的呈现在哪里。 介绍中说&#xff0c;《图解HTTP》适合作为第一本网络协议书。确实&#xff0c;它就像一座桥梁&#xff0c;连接…...

LLMs瞬间获得视觉与听觉感知,无需专门训练:Meta的创新——在图像、音频和视频任务上实现最优性能。

引言&#xff1a; 问题&#xff1a; 当前的多模态任务&#xff08;如图像、视频、音频描述生成、编辑、生成等&#xff09;通常需要针对特定任务训练专门的模型&#xff0c;而现有的方法在跨模态泛化方面存在局限性&#xff0c;难以适应新任务。此外&#xff0c;多模态嵌入反演…...

自研有限元软件与ANSYS精度对比-Bar3D2Node三维杆单元模型-央视大裤衩实例

目录 1、“央视大裤衩”自研有限元软件求解 1.1、选择单元类型 1.2、导入“央视大裤衩”工程 1.3、节点坐标定义 1.4、单元连接关系、材料定义 1.5、约束定义 1.6、外载定义 1.7、矩阵求解 1.8、变形云图展示 1.9、节点位移 1.10、单元应力 1.11、节点支反力 2、“…...

kubernetes 高可用集群搭建

在生产环境中部署 Kubernetes 集群时&#xff0c;确保其高可用性&#xff08;High Availability, HA&#xff09;是至关重要的。高可用性不仅意味着减少服务中断时间&#xff0c;还能提高系统的稳定性和可靠性。本文将详细介绍如何搭建一个高可用的 Kubernetes 集群&#xff0c…...

【C++】STL——vector底层实现

目录 &#x1f495; 1.vector三个核心 &#x1f495;2.begin函数&#xff0c;end函数的实现&#xff08;简单略讲&#xff09; &#x1f495;3.size函数&#xff0c;capacity函数的实现 &#xff08;简单略讲&#xff09; &#x1f495;4.reserve函数实现 &#xff08;细节…...

数据结构初探:链表之单链表篇

本文图皆为作者手绘,所有代码基于vs2022运行测试 系列文章目录 数据结构初探:顺序表篇 文章目录 系列文章目录前言一、链表基础概念二、链表的分类简化边界条件处理使代码更清晰简洁提高程序稳定性 1.单链表(不带头不循环的单链表);1.1存储结构;1.2准备工作1.3链表增删查改的实…...

介绍一下Mybatis的底层原理(包括一二级缓存)

表面上我们的就是Sql语句和我们的java对象进行映射&#xff0c;然后Mapper代理然后调用方法来操作数据库 底层的话我们就涉及到Sqlsession和Configuration 首先说一下SqlSession&#xff0c; 它可以被视为与数据库交互的一个会话&#xff0c;用于执行 SQL 语句&#xff08;Ex…...

Linux基础 ——tmux vim 以及基本的shell语法

Linux 基础 ACWING y总的Linux基础课&#xff0c;看讲义作作笔记。 tmux tmux 可以干嘛&#xff1f; tmux可以分屏多开窗口&#xff0c;可以进行多个任务&#xff0c;断线&#xff0c;不会自动杀掉正在进行的进程。 tmux – session(会话&#xff0c;多个) – window(多个…...

64位的谷歌浏览器Chrome/Google Chrome

64位的谷歌浏览器Chrome/Google Chrome 在百度搜索关键字:chrome&#xff0c;即可下载官方的“谷歌浏览器Chrome/Google Chrome”&#xff0c;但它可能是32位的&#xff08;切记注意网址&#xff1a;https://www.google.cn/....&#xff0c; 即&#xff1a;google.cn&#xff…...

jetson编译torchvision出现 No such file or directory: ‘:/usr/local/cuda/bin/nvcc‘

文章目录 1. 完整报错2. 解决方法 1. 完整报错 jetson编译torchvision,执行python3 setup.py install --user遇到报错 running build_ext error: [Errno 2] No such file or directory: :/usr/local/cuda/bin/nvcc完整报错信息如下&#xff1a; (pytorch) nxnx-desktop:~/Do…...

多线程创建方式三:实现Callable接口

实现Callable第三种方式存在的原因 作用&#xff1a;可以返回线程执行完毕后的结果。 前两种线程创建方式都存在的一个问题&#xff1a;假如线程执行完毕后有一些数据需要返回,他们重写的run方法均不能直接返回结果。 如何实现 ● JDK 5.0提供了Callable接口和FutureTask类来…...

Linux下的编辑器 —— vim

目录 1.什么是vim 2.vim的模式 认识常用的三种模式 三种模式之间的切换 命令模式和插入模式的转化 命令模式和底行模式的转化 插入模式和底行模式的转化 3.命令模式下的命令集 光标移动相关的命令 复制粘贴相关命令 撤销删除相关命令 查找相关命令 批量化注释和去…...

Docker技术相关学习二

一、Docker简介 1.Docker之父Solomon Hykes形容docker就像传统的货运集装箱。 2.docker的特点和优势&#xff1a; 轻量级虚拟化&#xff1a;Docker容器相较于传统的虚拟机更加的轻量和高效&#xff0c;能够快速的启动和停止来节省系统资源。 一致性&#xff1a;确保应用程序在不…...

【人工智能】多模态学习在Python中的应用:结合图像与文本数据的深度探索

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 多模态学习是人工智能领域的一个重要研究方向,旨在通过结合多种类型的数据(如图像、文本、音频等)来提高模型的性能。本文将深入探讨多模…...

【MySQL】常用语句

目录 1. 数据库操作2. 表操作3. 数据操作&#xff08;CRUD&#xff09;4. 高级查询5. 索引管理6. 用户与权限7. 数据导入导出8. 事务控制9. 其他实用语句注意事项 如果这篇文章对你有所帮助&#xff0c;渴望获得你的一个点赞&#xff01; 1. 数据库操作 创建数据库 CREATE DATA…...

Docker网络基础

一、Docker网络基础 1.docker安装后会自动创建3中网络&#xff0c;分别为bridge host none docker network ls 2.docker原生bridge网络&#xff1a; docker安装时会创建一个名为docker0的linux bridge,新建的容器会自动桥接到这个接口 bridge模式下没有公有ip,只有宿主机可以…...

重新刷题求职2-DAY2

977. 有序数组的平方 给你一个按 非递减顺序 排序的整数数组 nums&#xff0c;返回 每个数字的平方 组成的新数组&#xff0c;要求也按 非递减顺序 排序。 示例 1&#xff1a; 输入&#xff1a;nums [-4,-1,0,3,10] 输出&#xff1a;[0,1,9,16,100] 解释&#xff1a;平方后…...

[STM32 标准库]EXTI应用场景 功能框图 寄存器

一、EXTI 外部中断在嵌入式系统中有广泛的应用场景&#xff0c;如按钮开关控制&#xff0c;传感器触发&#xff0c;通信接口中断等。其原理都差不多&#xff0c;STM32会对外部中断引脚的边沿进行检测&#xff0c;若检测到相应的边沿会触发中断&#xff0c;在中断中做出相应的处…...

Slint的学习

Slint是什么 Slint是一个跨平台的UI工具包&#xff0c;支持windows,linux,android,ios,web&#xff0c;可以用它来构建申明式UI,后端代码支持rust,c,python,nodejs等语言。 开源地址&#xff1a;https://github.com/slint-ui/slint 镜像地址&#xff1a;https://kkgithub.com/…...

STM32 DMA+AD多通道

接线图 代码配置 ADC单次扫描DMA单次转运模式 uint16_t AD_Value[4]; //DMAAD多通道 void DMA_Config(void) {//定义结构体变量 GPIO_InitTypeDef GPIO_InitStructure;//定义GPIO结构体变量 ADC_InitTypeDef ADC_InitStructure; //定义ADC结构体变量 DMA_InitTypeDef DMA_In…...

如何构建ObjC语言编译环境?构建无比简洁的clang编译ObjC环境?Windows搭建Swift语言编译环境?

如何构建ObjC语言编译环境? 除了在线ObjC编译器&#xff0c;本地环境Windows/Mac/Linux均可以搭建ObjC编译环境。 Mac自然不用多说&#xff0c;ObjC是亲儿子。(WSL Ubuntu 22.04) Ubuntu可以安装gobjc/gnustep和gnustep-devel构建编译环境。 sudo apt-get install gobjc gnus…...

【C语言】指针详解:概念、类型与解引用

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C语言 文章目录 &#x1f4af;前言&#x1f4af;指针的基本概念1. 什么是指针2. 指针的基本操作 &#x1f4af;指针的类型1. 指针的大小2. 指针类型与所指向的数据类型3. 指针类型与数据访问的关系4. 指针类型的实际意…...

VoIP中常见术语

在 VoIP&#xff08;Voice over Internet Protocol&#xff0c;基于互联网协议的语音传输&#xff09;技术中&#xff0c;涉及许多专业术语。以下是常见术语及其含义&#xff1a; 1. 核心协议相关 SIP&#xff08;Session Initiation Protocol&#xff0c;会话发起协议&#xf…...

360嵌入式开发面试题及参考答案

解释一下 802.11ax 和 802.11ac/n 有什么区别 速度与带宽 802.11n 支持的最高理论速率为 600Mbps,802.11ac 进一步提升,单流最高可达 866.7Mbps,多流情况下能达到更高,如 1.3Gbps 等。而 802.11ax(Wi-Fi 6)引入了更多先进技术,理论最高速率可达 9.6Gbps,相比前两者有大…...

物理群晖SA6400核显直通win10虚拟机(VMM)

写在前面&#xff1a;请先确保你的核显驱动支持开启SR-IOV 确保你的BIOS开启了以下选项&#xff1a; VT-D VMX IOMMU Above 4G ResizeBAR 自行通过以下命令确认支持情况&#xff1a; dmesg | grep -i iommudmesg | grep DMAR分配1个虚拟vGPU&#xff1a;echo 1 | sudo tee /sy…...