C# 13 和 .NET 9 全知道 :5 构建您自己的类型——面向对象编程 (3)
yuyutoo 2025-01-27 01:05 3 浏览 0 评论
将字段设置为只读
通常,对于不应更改的字段,将其标记为只读是一个更好的选择:
- 在 Person.cs 中,添加一个声明来声明一个实例只读字段以存储一个人的家园星球,如下所示代码:
// Read-only fields: Values that can be set at runtime.
public readonly string HomePlanet = "Earth";
在 Program.cs 中,添加一条语句将 Bob 的名字和家园星球写入控制台,如下所示:
// Read-only fields are accessible via the variable.
WriteLine(#34;{bob.Name} was born on {bob.HomePlanet}.");
- 运行 PeopleApp 项目并查看结果,如下所示输出:
Bob Smith was born on Earth.
良好实践:使用只读字段而非常量字段,有两个重要原因:值可以在运行时计算或加载,并且可以使用任何可执行语句表示。因此,只读字段可以使用构造函数或字段赋值来设置。对只读字段的每个引用都是活动引用,因此任何未来的更改都将被调用代码正确反映。
您也可以声明 static readonly 字段,其值将在该类型的所有实例之间共享。
要求在实例化时设置字段
C# 11 引入了 required 修饰符。如果您在字段或属性上使用它,编译器将确保在实例化时设置字段或属性的值。它需要针对.NET 7 或更高版本,因此我们需要首先创建一个新的类库:
- 在 Chapter05 解决方案中,添加一个名为 PacktLibraryModern 的新类库项目,目标为.NET 9。(支持 required 修饰符的最旧版本是.NET 7。)
- 在 PacktLibraryModern 项目中,将 Class1.cs 重命名为 Book.cs 。
- 修改代码文件内容,使类具有四个字段,其中两个字段设置为 required ,如下所示代码:
namespace Packt.Shared;
public class Book
{
// Needs .NET 7 or later as well as C# 11 or later.
public required string? Isbn;
public required string? Title;
// Works with any version of .NET.
public string? Author;
public int PageCount;
}
请注意,所有 three 字符串属性都是可空的。将属性或字段设置为 required 并不意味着它不能是 null 。它只是意味着它必须显式设置为 null 。
- 在 PeopleApp 控制台应用程序项目中,添加对 PacktLibraryModern 类库项目的引用:如果您使用 Visual Studio,则在解决方案资源管理器中,选择 PeopleApp 项目,转到项目 | 添加项目引用…,勾选复选框以选择 PacktLibraryModern 项目,然后单击确定。如果您使用 VS Code,请编辑 PeopleApp.csproj 以添加对 PacktLibraryModern 的项目引用,如以下标记所示:
<ItemGroup>
<ProjectReference Include=
"..\PacktLibraryNet2\PacktLibraryNet2.csproj" />
<ProjectReference Include=
"..\PacktLibraryModern\PacktLibraryModern.csproj" />
</ItemGroup>
- 构建 PeopleApp 项目。这将编译其引用的依赖项并将类库 .dll 复制到本地 bin 文件夹的正确子目录中。
- 在 PeopleApp 项目中,在 Program.cs 中,尝试实例化一个 Book 而不设置 Isbn 和 Title 字段,如下所示代码:
Book book = new();
请注意,您将看到编译器错误,如下所示输出:
C:\cs13net9\Chapter05\PeopleApp\Program.cs(137,13): error CS9035: Required member 'Book.Isbn' must be set in the object initializer or attribute constructor. [C:\cs13net9\Chapter05\PeopleApp\PeopleApp.csproj]
C:\cs13net9\Chapter05\PeopleApp\Program.cs(137,13): error CS9035: Required member 'Book.Title' must be set in the object initializer or attribute constructor. [C:\cs13net9\Chapter05\PeopleApp\PeopleApp.csproj]
0 Warning(s)
2 Error(s)
在 Program.cs 中,修改语句以使用对象初始化语法设置两个必需的属性,如下所示代码中突出显示:
Book book = new()
{
Isbn = "978-1803237800",
Title = "C# 12 and .NET 8 - Modern Cross-Platform Development Fundamentals"
};
- 请注意,现在该语句编译无误。
- 在 Program.cs 中,添加一条输出关于书籍信息的语句,如下所示代码:
WriteLine("{0}: {1} written by {2} has {3:N0} pages.",
book.Isbn, book.Title, book.Author, book.PageCount);
在运行项目并查看输出之前,让我们谈谈一种初始化类型(或属性)字段的替代方法。
初始化字段使用构造函数
字段通常需要在运行时初始化。您可以在创建类实例时调用的构造函数中执行此操作,使用 new 关键字。构造函数在代码设置任何字段之前执行:
- 在 Person.cs 中,在现有的只读 HomePlanet 字段之后添加语句以定义第二个只读字段,然后在构造函数中设置 Name 和 Instantiated 字段,如下代码所示:
// Read-only fields: Values that can be set at runtime.
public readonly string HomePlanet = "Earth";
public readonly DateTime Instantiated;
#endregion
#region Constructors: Called when using new to instantiate a type.
public Person()
{
// Constructors can set default values for fields
// including any read-only fields like Instantiated.
Name = "Unknown";
Instantiated = DateTime.Now;
}
#endregion
在 Program.cs 中,添加语句以实例化一个新的 Person 对象,然后输出其初始字段值,如下所示:
Person blankPerson = new();
WriteLine(format:
"{0} of {1} was created at {2:hh:mm:ss} on a {2:dddd}.",
arg0: blankPerson.Name,
arg1: blankPerson.HomePlanet,
arg2: blankPerson.Instantiated);
运行 PeopleApp 项目,并从关于书籍的代码以及空白人物两方面查看结果,如下所示输出:
978-1803237800: C# 12 and .NET 8 - Modern Cross-Platform Development Fundamentals written by has 0 pages.
Unknown of Earth was created at 11:58:12 on a Sunday
定义多个构造函数
您可以在一个类型中拥有多个构造函数。这特别有助于鼓励开发者为字段设置初始值:
- 在 Person.cs 中,添加语句以定义第二个构造函数,允许开发者设置人的姓名和家园行星的初始值,如下所示代码:
public Person(string initialName, string homePlanet)
{
Name = initialName;
HomePlanet = homePlanet;
Instantiated = DateTime.Now;
}
在 Program.cs 中,添加语句使用两个参数的构造函数创建另一个人,如下所示代码:
Person gunny = new(initialName: "Gunny", homePlanet: "Mars");
WriteLine(format:
"{0} of {1} was created at {2:hh:mm:ss} on a {2:dddd}.",
arg0: gunny.Name,
arg1: gunny.HomePlanet,
arg2: gunny.Instantiated);
- 运行 PeopleApp 项目并查看结果:
Gunny of Mars was created at 11:59:25 on a Sunday
设置构造函数中的必填字段
现在,让我们回到 Book 类示例及其 required 字段:
- 在 PacktLibraryModern 项目中,在 Book.cs 中,添加语句定义一对构造函数,一个支持对象初始化语法,另一个用于设置两个必需的属性,如下代码所示:
public class Book
{
// Constructor for use with object initializer syntax.
public Book() { }
// Constructor with parameters to set required fields.
public Book(string? isbn, string? title)
{
Isbn = isbn;
Title = title;
}
在 Program.cs 中,取消注释使用对象初始化语法实例化书籍的语句,添加使用构造函数实例化书籍的语句,然后设置书籍的非 required 属性,如下代码所示:
/*
// Instantiate a book using object initializer syntax.
Book book = new()
{
Isbn = "978-1803237800",
Title = "C# 12 and .NET 8 - Modern Cross-Platform Development Fundamentals"
};
*/
Book book = new(isbn: "978-1803237800", title:
"C# 12 and .NET 8 - Modern Cross-Platform Development Fundamentals")
{
Author = "Mark J. Price",
PageCount = 821
};
- 请注意,您将像之前一样看到编译器错误,因为编译器无法自动判断调用构造函数将设置这两个 required 属性。
- 在 PacktLibraryModern 项目中,在 Book.cs 中导入命名空间以执行代码分析,然后使用属性装饰构造函数,告诉编译器它设置了所有必需的属性和字段,如下面的代码所示:
using System.Diagnostics.CodeAnalysis; // To use [SetsRequiredMembers].
namespace Packt.Shared;
public class Book
{
public Book() { } // For use with initialization syntax.
[SetsRequiredMembers]
public Book(string isbn, string title)
- 在 Program.cs 中,注意现在调用构造函数的语句编译没有错误。
- 可选地,运行 PeopleApp 项目以确认其行为符合预期,如下所示输出:
978-1803237800: C# 12 and .NET 8 - Modern Cross-Platform Development Fundamentals written by Mark J. Price has 821 pages.
更多信息:您可以在以下链接中了解有关 required 字段以及如何使用构造函数设置它们的更多信息:https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/required。
构造函数是一种特殊的方法类别。让我们更详细地看看方法。
与方法和元组一起工作
方法是一个类型的成员,它执行一组语句。它们是属于一个类型的函数。
从方法中返回值
方法可以返回单个值或无返回值:
- 一种执行某些操作但不返回值的函数,在函数名称前使用 void 类型来表示。
- 一种执行某些操作并返回值的函数,在函数名之前用返回值的类型来表示这一点。
例如,在下一个任务中,您将创建两个方法:
- WriteToConsole :这将执行一个操作(将一些文本写入控制台),但方法将不会返回任何内容,由 void 关键字表示。
- GetOrigin :这将返回一个文本值,由 string 关键字指示。
让我们编写代码:
- 在 Person.cs 中,添加语句以定义我之前描述的两个方法,如下所示:
#region Methods: Actions the type can perform.
public void WriteToConsole()
{
WriteLine(#34;{Name} was born on a {Born:dddd}.");
}
public string GetOrigin()
{
return #34;{Name} was born on {HomePlanet}.";
}
#endregion
在 Program.cs 中,添加调用两个方法的语句,如下所示代码:
bob.WriteToConsole();
WriteLine(bob.GetOrigin());
运行 PeopleApp 项目并查看结果,如下所示输出
Bob Smith was born on a Wednesday.
Bob Smith was born on Earth.
定义和传递方法参数
方法可以通过传递参数来改变其行为。参数的定义有点像变量声明,但位于方法声明的括号内,就像您在本章前面看到的构造函数那样。让我们看看更多示例:
- 在 Person.cs 中,添加定义两个方法的语句,第一个不带参数,第二个带一个参数,如下所示:
public string SayHello()
{
return #34;{Name} says 'Hello!'";
}
public string SayHelloTo(string name)
{
return #34;{Name} says 'Hello, {name}!'";
}
在 Program.cs 中,添加调用两个方法的语句,并将返回值写入控制台,如下所示:
WriteLine(bob.SayHello());
WriteLine(bob.SayHelloTo("Emily"));
运行 PeopleApp 项目并查看结果:
Bob Smith says 'Hello!'
Bob Smith says 'Hello, Emily!'
当输入调用方法的语句时,IntelliSense 会显示一个包含方法名称、任何参数的类型和方法返回类型的工具提示。
过载方法
而不是有两个不同的方法名,我们可以给这两个方法相同的名字。这是允许的,因为每个方法都有不同的签名。
方法签名是在调用方法时可以传递的参数类型列表。重载方法必须在参数类型列表上有所不同。两个重载方法不能有相同的参数类型列表,并且仅在返回类型上有所不同。让我们编写一个示例:
- 在 Person.cs 中,将 SayHelloTo 方法的名字更改为 SayHello 。
- 在 Program.cs 中,将方法调用更改为使用 SayHello 方法,并注意该方法的快速信息显示它有额外的重载,1/2 以及 2/2,在 Visual Studio 中,尽管其他代码编辑器可能不同,如图 5.3 所示:
好的做法:使用重载方法简化您的类,使其看起来拥有更少的方法。
传递可选参数
另一种简化方法是将参数设置为可选。您可以通过在方法参数列表中为参数分配默认值来使参数可选。可选参数必须始终位于参数列表的末尾。
我们现在将创建一个包含三个可选参数的方法:
- 在 Person.cs 中,添加定义方法的语句,如下所示代码:
public string OptionalParameters(string command = "Run!",
double number = 0.0, bool active = true)
{
return string.Format(
format: "command is {0}, number is {1}, active is {2}",
arg0: command,
arg1: number,
arg2: active);
}
在 Program.cs 中,添加一条语句来调用该方法并将返回值写入控制台,如下所示:
WriteLine(bob.OptionalParameters());
- 观察 IntelliSense 在您键入代码时出现。您将看到一个工具提示,显示三个可选参数及其默认值。
- 运行 PeopleApp 项目并查看结果,如下所示输出:
command is Run!, number is 0, active is True
在 Program.cs 中,添加一条语句以传递 string 值给 command 参数和 double 值给 number 参数,如下所示代码:
WriteLine(bob.OptionalParameters("Jump!", 98.5));
运行 PeopleApp 项目并查看结果,如下所示输出:
command is Jump!, number is 98.5, active is True
默认的 command 和 number 参数值已被替换,但 active 的默认值仍然是 true 。
在调用方法时命名参数值
可选参数通常在调用方法时与命名参数结合使用,因为命名参数允许以不同于声明时的顺序传递值:
- 在 Program.cs 中,添加一个语句以传递 string 值给 command 参数和 double 值给 number 参数,但使用命名参数,这样它们传递的顺序可以互换,如下面的代码所示:
WriteLine(bob.OptionalParameters(number: 52.7, command: "Hide!"));
运行 PeopleApp 项目并查看结果,如下所示输出:
command is Hide!, number is 52.7, active is True
您甚至可以使用命名参数来跳过可选参数。
- 在 Program.cs 中,添加一条语句以使用位置顺序传递 string 值给 command 参数,跳过 number 参数,并使用命名 active 参数,如下所示:
WriteLine(bob.OptionalParameters("Poke!", active: false));
运行 PeopleApp 项目并查看结果,如下所示输出:
command is Poke!, number is 0, active is False
良好的实践:虽然您可以混合使用命名参数和位置参数值,但大多数开发者更喜欢阅读在同一个方法调用中使用一种或另一种参数值的代码。
混合可选和必选参数
目前, OptionalParameters 方法中的所有参数都是可选的。如果其中一个参数是必需的怎么办?
- 在 Person.cs 中,向 OptionalParameters 方法添加一个不带默认值的第四个参数,如以下代码所示:
public string OptionalParameters(string command = "Run!",
double number = 0.0, bool active = true, int count)
- 构建项目并注意编译错误:
Error CS1737 Optional parameters must appear after all required parameters.
在 OptionalParameters 方法中,将 count 参数移动到可选参数之前,如下所示:
public string OptionalParameters(int count,
string command = "Run!",
double number = 0.0, bool active = true)
在 Program.cs 中,修改所有对 OptionalParameters 方法的调用,将 int 值作为第一个参数传递,例如,如下代码所示:
WriteLine(bob.OptionalParameters(3));
WriteLine(bob.OptionalParameters(3, "Jump!", 98.5));
WriteLine(bob.OptionalParameters(3, number: 52.7, command: "Hide!"));
WriteLine(bob.OptionalParameters(3, "Poke!", active: false));
记住,如果你命名了参数,那么你可以改变它们的顺序,例如: bob.OptionalParameters(number: 52.7, command: "Hide!", count: 3) 。
- 当您调用 OptionalParameters 方法时,注意 Visual Studio 中显示的提示信息,其中包含一个必需参数、三个可选参数及其默认值,如图 5.4 所示:
控制参数传递的方式
当参数传递给一个方法时,它可以以几种方式之一传递:
- 通过值(这是默认值):将这些视为单向的。尽管值可以更改,但这只会影响方法中的参数。
- 作为一个 out 参数:将这些视为单向输出。 out 参数在其声明中不能分配默认值,也不能留作未初始化。必须在方法内部设置它们;否则,编译器将给出错误。
- 通过引用作为 ref 参数:将这些视为进出。像 out 参数一样, ref 参数也不能有默认值,但由于它们可以在方法外部设置,因此不需要在方法内部设置。
- 作为一个 in 参数:将这些视为只读的引用参数。 in 参数的值不能被更改,如果尝试修改,编译器将显示错误。
让我们看看一些在方法中传递参数的例子:
- 在 Person.cs 中,添加语句定义一个具有三个参数的方法,一个 in 参数,一个 ref 参数和一个 out 参数,如下所示的方法:
public void PassingParameters(int w, in int x, ref int y, out int z)
{
// out parameters cannot have a default and they
// must be initialized inside the method.
z = 100;
// Increment each parameter except the read-only x.
w++;
// x++; // Gives a compiler error!
y++;
z++;
WriteLine(#34;In the method: w={w}, x={x}, y={y}, z={z}");
}
在 Program.cs 中,添加语句声明一些 int 变量并将它们传递到方法中,如下所示:
int a = 10;
int b = 20;
int c = 30;
int d = 40;
WriteLine(#34;Before: a={a}, b={b}, c={c}, d={d}");
bob.PassingParameters(a, b, ref c, out d);
WriteLine(#34;After: a={a}, b={b}, c={c}, d={d}");
运行 PeopleApp 项目并查看结果,如下所示输出:
Before: a=10, b=20, c=30, d=40
In the method: w=11, x=20, y=31, z=101
After: a=10, b=20, c=31, d=101
请注意以下关于前一个输出的内容:
- 当默认通过参数传递变量时,传递的是其当前值,而不是变量本身。因此, w 有 a 变量的值的副本。 a 变量在 w 增加到 11 后仍保留其原始值 10 。
- 当将变量作为 in 参数传递时,变量的引用会被传递到方法中。因此, x 是 b 的引用。如果在方法执行过程中, b 变量被其他进程增加,那么 x 参数会显示出来。
- 当将变量作为 ref 参数传递时,变量的引用被传递到方法中。因此, y 是 c 的引用。当 y 参数增加时, c 变量会递增。
- 当将变量作为 out 参数传递时,变量的引用被传递到方法中。因此, z 是 d 的引用。 d 变量的值将被方法内部执行的代码所替换。
我们可以通过不将值 40 分配给 d 变量来简化 Main 方法中的代码,因为这个值无论如何都会被替换。在 C# 7 及以后的版本中,我们可以简化使用 out 参数的代码。
- 在 Program.cs 中,添加语句以声明更多变量,包括一个名为 h 的 out 参数,该参数在行内声明,如下所示:
int e = 50;
int f = 60;
int g = 70;
WriteLine(#34;Before: e={e}, f={f}, g={g}, h doesn't exist yet!");
// Simplified C# 7 or later syntax for the out parameter.
bob.PassingParameters(e, f, ref g, out int h);
WriteLine(#34;After: e={e}, f={f}, g={g}, h={h}");
运行 PeopleApp 项目并查看结果,如下所示输出:
Before: e=50, f=60, g=70, h doesn't exist yet!
In the method: w=51, x=60, y=71, z=101
After: e=50, f=60, g=71, h=101
传递可变数量的参数
C#中的 params 关键字用于指定一个可以接受可变数量参数的方法参数。它允许你将参数数组传递给方法,或者传递一个编译器会自动转换为数组的参数列表。
从 C# 13 及以后版本开始,除了传递数组外,还可以传递任何可以通过集合表达式构造的类型,例如 List<T> 或 IEnumerable<T> 。集合表达式在第八章“使用常见.NET 类型”中有详细说明,但基本上,您可以通过在方括号中包围以逗号分隔的项目列表来定义一个项目集合 [ ] 。
使用 params 的好处包括灵活性。它允许方法接受任意数量的参数,并且易于使用,因为它通过避免在调用方法之前显式创建数组来简化方法签名。
在使用 params 关键字时有一些考虑因素:
- params 关键字只能用于方法中的一个参数,并且如果方法有多个参数,它必须是最后一个参数。
- 您可以将单个参数传递,编译器会自动将它们打包成一个数组。或者,您也可以传递一个数组或集合表达式。
- 当使用 params 时,您可以调用该方法而不传递任何参数给该参数,并将传递一个空数组。
让我们看看一些代码示例:
- 在 Person.cs 中,添加语句定义一个带有两个参数的方法,一个普通参数和一个 params 参数,如下所示的方法:
public void ParamsParameters(
string text, params int[] numbers)
{
int total = 0;
foreach(int number in numbers)
{
total += number;
}
WriteLine(#34;{text}: {total}");
}
- 在 C# 12 及之前版本中, params int[] 必须是一个数组,尽管项目可以是任何数据类型,而不仅仅是 int 。在 C# 13 及以后版本中, params int[] 可以是集合表达式支持的任何数据类型,如 params List<int> 或 IEnumerable<int> ,尽管项目可以是任何数据类型,而不仅仅是 int 。
- 在 Program.cs 中,添加语句以多种方式将字符串和一些数字传递到方法中,如下所示代码:
bob.ParamsParameters("Sum using commas",
3, 6, 1, 2);
bob.ParamsParameters("Sum using collection expression",
[3, 6, 1, 2]);
bob.ParamsParameters("Sum using explicit array",
new int[] { 3, 6, 1, 2 });
bob.ParamsParameters("Sum (empty)");
运行 PeopleApp 项目并查看结果,如下所示输出:
Sum using commas: 12
Sum using collection expression: 12
Sum using explicit array: 12
Sum (empty): 0
params 关键字是 C# 中一个强大的功能,它通过允许方法接受可变数量的参数,增强了代码的灵活性和可读性。
相关推荐
- Mysql和Oracle实现序列自增(oracle创建序列的sql)
-
Mysql和Oracle实现序列自增/*ORACLE设置自增序列oracle本身不支持如mysql的AUTO_INCREMENT自增方式,我们可以用序列加触发器的形式实现,假如有一个表T_WORKM...
- 关于Oracle数据库12c 新特性总结(oracle数据库19c与12c)
-
概述今天主要简单介绍一下Oracle12c的一些新特性,仅供参考。参考:http://docs.oracle.com/database/121/NEWFT/chapter12102.htm#NEWFT...
- MySQL CREATE TABLE 简单设计模板交流
-
推荐用MySQL8.0(2018/4/19发布,开发者说同比5.7快2倍)或同类型以上版本....
- mysql学习9:创建数据库(mysql5.5创建数据库)
-
前言:我也是在学习过程中,不对的地方请谅解showdatabases;#查看数据库表createdatabasename...
- MySQL面试题-CREATE TABLE AS 与CREATE TABLE LIKE的区别
-
执行"CREATETABLE新表ASSELECT*FROM原表;"后,新表与原表的字段一致,但主键、索引不会复制到新表,会把原表的表记录复制到新表。...
- Nike Dunk High Volt 和 Bright Spruce 预计将于 12 月推出
-
在街上看到的PandaDunk的超载可能让一些球鞋迷们望而却步,但Dunk的浪潮仍然强劲,看不到尽头。我们看到的很多版本都是为女性和儿童制作的,这种新配色为后者引入了一种令人耳目一新的新选择,而...
- 美国多功能舰载雷达及美国海军舰载多功能雷达系统技术介绍
-
多功能雷达AN/SPY-1的特性和技术能力,该雷达已经在美国海军服役了30多年,其修改-AN/SPY-1A、AN/SPY-1B(V)、AN/SPY-1D、AN/SPY-1D(V),以及雷神...
- 汽车音响怎么玩,安装技术知识(汽车音响怎么玩,安装技术知识视频)
-
全面分析汽车音响使用或安装技术常识一:主机是大多数人最熟习的音响器材,有关主机的各种性能及规格,也是耳熟能详的事,以下是一些在使用或安装时,比较需要注意的事项:LOUDNESS:几年前的主机,此按...
- 【推荐】ProAc Response系列扬声器逐个看
-
有考牌(公认好声音)扬声器之称ProAcTablette小音箱,相信不少音响发烧友都曾经,或者现在依然持有,正当大家逐渐掌握Tablette的摆位设定与器材配搭之后,下一步就会考虑升级至表现更全...
- #本站首晒# 漂洋过海来看你 — BLACK&DECKER 百得 BDH2000L无绳吸尘器 开箱
-
作者:初吻给了烟sco混迹张大妈时日不短了,手没少剁。家里有了汪星人,吸尘器使用频率相当高,偶尔零星打扫用卧式的实在麻烦(汪星人:你这分明是找借口,我掉毛是满屋子都有,铲屎君都是用卧式满屋子吸的,你...
- 专题|一个品牌一件产品(英国篇)之Quested(罗杰之声)
-
Quested(罗杰之声)代表产品:Q212FS品牌介绍Quested(罗杰之声)是录音监听领域的传奇品牌,由英国录音师RogerQuested于1985年创立。在成立Quested之前,Roger...
- 常用半导体中英对照表(建议收藏)(半导体英文术语)
-
作为一个源自国外的技术,半导体产业涉及许多英文术语。加之从业者很多都有海外经历或习惯于用英文表达相关技术和工艺节点,这就导致许多英文术语翻译成中文后,仍有不少人照应不上或不知如何翻译。为此,我们整理了...
- Fyne Audio F502SP 2.5音路低音反射式落地音箱评测
-
FyneAudio的F500系列,有新成员了!不过,新成员不是新的款式,却是根据原有款式提出特别版。特别版产品在原有型号后标注了SP字样,意思是SpecialProduction。Fyne一共推出...
- 有哪些免费的内存数据库(In-Memory Database)
-
以下是一些常见的免费的内存数据库:1.Redis:Redis是一个开源的内存数据库,它支持多种数据结构,如字符串、哈希表、列表、集合和有序集合。Redis提供了快速的读写操作,并且支持持久化数据到磁...
- RazorSQL Mac版(SQL数据库查询工具)
-
RazorSQLMac特别版是一款看似简单实则功能非常出色的SQL数据库查询、编辑、浏览和管理工具。RazorSQLformac特别版可以帮你管理多个数据库,支持主流的30多种数据库,包括Ca...
你 发表评论:
欢迎- 一周热门
-
-
前端面试:iframe 的优缺点? iframe有那些缺点
-
带斜线的表头制作好了,如何填充内容?这几种方法你更喜欢哪个?
-
漫学笔记之PHP.ini常用的配置信息
-
其实模版网站在开发工作中很重要,推荐几个参考站给大家
-
推荐7个模板代码和其他游戏源码下载的网址
-
[干货] JAVA - JVM - 2 内存两分 [干货]+java+-+jvm+-+2+内存两分吗
-
正在学习使用python搭建自动化测试框架?这个系统包你可能会用到
-
织梦(Dedecms)建站教程 织梦建站详细步骤
-
【开源分享】2024PHP在线客服系统源码(搭建教程+终身使用)
-
2024PHP在线客服系统源码+完全开源 带详细搭建教程
-
- 最近发表
-
- Mysql和Oracle实现序列自增(oracle创建序列的sql)
- 关于Oracle数据库12c 新特性总结(oracle数据库19c与12c)
- MySQL CREATE TABLE 简单设计模板交流
- mysql学习9:创建数据库(mysql5.5创建数据库)
- MySQL面试题-CREATE TABLE AS 与CREATE TABLE LIKE的区别
- Nike Dunk High Volt 和 Bright Spruce 预计将于 12 月推出
- 美国多功能舰载雷达及美国海军舰载多功能雷达系统技术介绍
- 汽车音响怎么玩,安装技术知识(汽车音响怎么玩,安装技术知识视频)
- 【推荐】ProAc Response系列扬声器逐个看
- #本站首晒# 漂洋过海来看你 — BLACK&DECKER 百得 BDH2000L无绳吸尘器 开箱
- 标签列表
-
- mybatis plus (70)
- scheduledtask (71)
- css滚动条 (60)
- java学生成绩管理系统 (59)
- 结构体数组 (69)
- databasemetadata (64)
- javastatic (68)
- jsp实用教程 (53)
- fontawesome (57)
- widget开发 (57)
- vb net教程 (62)
- hibernate 教程 (63)
- case语句 (57)
- svn连接 (74)
- directoryindex (69)
- session timeout (58)
- textbox换行 (67)
- extension_dir (64)
- linearlayout (58)
- vba高级教程 (75)
- iframe用法 (58)
- sqlparameter (59)
- trim函数 (59)
- flex布局 (63)
- contextloaderlistener (56)