原文:bit.ly/2VJxjxQ
作者:Richard
翻译:精致码农-王亮
说明:文中有大量的超链接,这些链接在公众号文章中被自动剔除,一部分包含超链接列表的小段落被我删减了,如果你对此感兴趣,请参考阅读原文。

我们很高兴地发布了 .NET 6 预览版 7。这是我们进入(两个)候选发布版(RC)之前的最后一个预览版。在我们放慢发布速度之前,团队一直在萤窗雪案,以完成最后一组功能。在这个版本中,你将看到各功能的最后一次抛光,一次到位地整合整个版本的大型功能。从此时起,团队将专注于使所有的功能达到统一的(高)质量,以便 .NET 6 为你的生产工作做好准备。

关于生产工作的话题,值得提醒大家的是,.NET 官网[1]和 Bing.com 从预览版 1 开始就一直运行在 .NET 6 上。我们正在与不同的团队(微软和其他公司)商谈有关进入生产的 .NET 6 RC 版本。如果你对此感兴趣,并希望得到相关的指导,请联系 dotnet@microsoft.com。我们始终很乐意与早期采用者交流。

你可以在这下载[2] Linux、macOS 和 Windows 的 .NET 6 预览版 7。

- 安装程序和二进制文件https://dotnet.microsoft.com/download/dotnet/6.0
- 容器镜像https://hub.docker.com/_/microsoft-dotnet
- Linux 包https://github.com/dotnet/core/blob/main/release-notes/6.0/install-linux.md
- 发布说明https://github.com/dotnet/core/blob/main/release-notes/6.0/README.md
- API 差异https://github.com/dotnet/core/tree/main/release-notes/6.0/preview/api-diff/preview7
- 已知问题https://github.com/dotnet/core/blob/main/release-notes/6.0/known-issues.md
- GitHub issue 跟踪https://github.com/dotnet/core/issues/6554

请参阅 .NET MAUI[3] 和 ASP.NET Core[4],了解更多关于客户端和 Web 应用场景的新内容。

.NET 6 预览版 7 已经在 Visual Studio 2022 预览版 3 中测试通过并得到支持。Visual Studio 2022 使你能够利用为 .NET 6 开发的 Visual Studio 工具,如 .NET MAUI 的开发、C# 应用程序的 Hot Reload、WebForms 的 Web Live,以及 IDE 体验中的其他性能改进。Visual Studio Code 也支持 .NET 6。

请查看我们新的对话帖[5],了解工程师之间关于最新的 .NET 功能的深入讨论。我们还发表了关于 C# 10 中的字符串插值和 .NET 6 中的预览功能 - 泛型 Math[6]

1.NET SDK:现代化的 C# 项目模板

我们更新了 .NET SDK 的模板,以使用最新的 C# 语言特性和模式。我们已经有一段时间没有在新的语言特性方面重新审视这些模板了。现在是时候了,我们将确保模板在未来使用新的功能。

以下是新模板中使用的语言特性:

  • 顶层语句

  • async Main

  • 全局 using 指令(通过 SDK 驱动的默认值)

  • File-scoped 命名空间

  • 目标类型 new 表达式

  • 可空(Nullable)引用类型

你可能会问,为什么我们要通过模板启用某些功能,而不是在项目以 .NET 6 为 Target 时默认启用这些功能。尽管我们可以要求你在升级应用程序到新版本的 .NET 时做一些工作,作为改善平台默认行为的交换条件,这使我们能够改进产品,而不会使项目文件随着时间的推移而变得复杂。然而,有些功能对于这种模式来说可能是相当具有破坏性的,比如可空(Nullable)的引用类型。无论是在什么时候,我们都不想把这些功能与升级体验联系在一起,而是想把这个选择权留给你。模板是一个风险更低的支点,在那里我们能够为新的代码设置新的“好的默认模型”,而不会产生那么多下游的后果。通过项目模板启用这些功能,我们得到了两全其美的结果:新代码开始时启用了这些功能,但现有的代码在你升级时不会受到影响。

控制台模板

控制台模板变化最大,通过顶层语句和全局引用指令,它现在是一个单行代码:

// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");

而以前的同一模板的 .NET 5 版本是这样的:

using System;namespace Company.ConsoleApplication1
{class Program{static void Main(string[] args){Console.WriteLine("Hello, World!");}}
}

控制台模板的项目文件也发生了变化,启用了可空(Nullable)引用类型的功能,例如:

<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><OutputType>Exe</OutputType><TargetFramework>net6.0</TargetFramework><Nullable>enable</Nullable></PropertyGroup></Project>

其他模板也可以实现可空(Nullable)引用类型、隐式全局引用和 File-scoped 命名空间,包括 ASP.NET Core 和 类库。

ASP.NET Web 模板

Web 模板也同样减少了代码行数,使用同样的功能:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();if (app.Environment.IsDevelopment())
{app.UseDeveloperExceptionPage();
}app.MapGet("/", () => "Hello World!");app.Run();

ASP.NET MVC 模板

MVC 模板的结构也类似。在这种情况下,我们将 Program.csStartup.cs 合并为一个文件(Program.cs),形成了进一步的简化:

var builder = WebApplication.CreateBuilder(args);// Add services to the container.
builder.Services.AddControllersWithViews();var app = builder.Build();// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{app.UseDeveloperExceptionPage();
}
else
{app.UseExceptionHandler("/Home/Error");// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.app.UseHsts();
}app.UseHttpsRedirection();
app.UseStaticFiles();app.UseRouting();app.UseAuthorization();app.MapControllerRoute(name: "default",pattern: "{controller=Home}/{action=Index}/{id?}");app.Run();

模板兼容性

关于使用新模板的兼容性问题,请参见以下内容:

  • 模板中的 C# 代码不被早期的 .NET 版本所支持[7]

  • 隐式命名空间引入[8]

2类库:反射 API 的可空性信息

可空引用类型[9]是编写可靠代码的一个重要特征。它在编写代码时非常有用,但在检查代码时却没有(直到现在)。新的反射 API[10] 使你能够确定一个给定方法的参数和返回值的可空性。这些新的 API 对于基于反射的工具和序列化来说是至关重要的,比如说:

就上下文而言,我们在 .NET 5 中为 .NET 库添加了可空标注[11](在.NET 6 中完成),并且正在为 ASP.NET Core 的这个版本做同样的工作。我们也看到开发者在他们的项目中采用了可空性(Nullability)[12]

可空性(Nullability)信息存在于使用自定义属性的元数据中[13]。原则上,任何人都已经可以读取自定义属性,然而,这并不理想,因为编码的消耗非同小可。

下面的例子演示了在几个不同的场景中使用新的 API。

获取顶层的可空性信息

想象一下,你正在实现一个序列化器。使用这些新的 API,序列化器可以检查一个给定的属性是否可以被设置为 null

private NullabilityInfoContext _nullabilityContext = new NullabilityInfoContext();private void DeserializePropertyValue(PropertyInfo p, object instance, object? value)
{if (value is null){var nullabilityInfo = _nullabilityContext.Create(p);if (nullabilityInfo.WriteState is not NullabilityState.Nullable){throw new MySerializerException($"Property '{p.GetType().Name}.{p.Name}'' cannot be set to null.");}}p.SetValue(instance, value);
}

获取嵌套的可空性信息

可空性对可以持有其他对象的对象有特殊处理,比如数组和元组。例如,你可以指定一个数组对象(作为一个变量,或者作为一个类型成员签名的一部分)必须是非空的,但是元素可以是空的,或者相反。这种额外的特殊性是可以通过新的反射 API 来检查的,例如:

class Data
{public string?[] ArrayField;public (string?, object) TupleField;
}
private void Print()
{Type type = typeof(Data);FieldInfo arrayField = type.GetField("ArrayField");FieldInfo tupleField = type.GetField("TupleField");NullabilityInfoContext context = new ();NullabilityInfo arrayInfo = context.Create(arrayField);Console.WriteLine(arrayInfo.ReadState);        // NotNullConsole.WriteLine(arrayInfo.Element.State);    // NullableNullabilityInfo tupleInfo = context.Create(tupleField);Console.WriteLine(tupleInfo.ReadState);                      // NotNullConsole.WriteLine(tupleInfo.GenericTypeArguments [0].State); // NullableConsole.WriteLine(tupleInfo.GenericTypeArguments [1].State); // NotNull
}

3类库:ZipFile 遵循 Unix 文件权限

System.IO.Compression.ZipFile 类现在可以在创建过程中捕获 Unix 文件权限,并在类似 Unix 的操作系统上提取压缩文件时设置文件权限。这一变化允许可执行文件在压缩包中被循环使用,这意味着你不再需要修改文件权限来使文件在解压缩包后可执行。它也同样遵循 usergroupother 读/写权限。

如果一个压缩包不包含文件权限(因为它是在 Windows 上创建的,或者使用了一个没有捕获权限的工具,比如早期的 .NET 版本),那么解压缩的文件就会得到默认的文件权限,就像其他新创建的文件一样。

Unix 的文件权限也适用于其他压缩工具,包括:

  • Info-ZIP

  • 7-Zip

4早期 .NET 7 功能预览:泛型 Math

对于 .NET 6,我们已经建立了将 API 标记为“预览”的能力[14]。这种新方法将使我们能够在多个主要版本中提供和发展预览功能。为了使用预览 API,项目需要明确选择使用的预览功能。如果你在没有明确选择的情况下使用预览功能,从 .NET 6 RC1 开始,你会看到带有可操作信息的构建错误。预览功能预计将在以后的版本中发生变化,可能会有破坏性的变化。这就是为什么他们要选择加入。

我们在 .NET 6 中预览的这些功能之一是静态抽象接口成员。这些允许你在接口中定义静态的抽象方法(包括操作符)。例如,现在可以实现代数泛型方法。对于一些人来说,这个功能将是我们今年交付的绝对突出的改进。这也许是自 Span<T> 以来最重要的新类型系统特性。

下面的例子是一个 IEnumerable<T>,由于 T 被限制为 INumber<T>,可能是一个 INumber<int>,所以能够对所有的数值进行求和。

public static T Sum<T>(IEnumerable<T> values)where T : INumber<T>
{T result = T.Zero;foreach (var value in values){result += value;}return result;
}

这是因为 INumber<T> 定义了各种(静态)操作符重载,必须由接口实现者来满足。IAdditionOperators 也许是最容易理解的新接口,INumber<T> 本身就是派生自这个接口。

这都是由一个新的功能提供的,它允许在接口中声明静态抽象成员。这使得接口可以公开运算符和其他静态方法,比如 ParseCreate,并且这些方法可以由派生类型实现。更多细节请参见我们的相关博文[15]

所有提到的功能都是 .NET 6 的预览版,不支持在生产中使用。我们将感谢您在使用中提供反馈。我们打算在 .NET 7 中继续发展和改进泛型 Math 功能以及支持它们的运行时和 C# 功能。我们希望对当前的体验进行突破性的改变,这也是为什么新的 API 被标记为“预览”的部分原因。

5类库:NativeMemory API

我们增加了新的本地内存分配 API[16],通过 System.Runtime.InteropServices.NativeMemory 公开。这些 API 相当于 C 语言中的 mallocfreerealloccalloc API,还包括用于进行对齐分配的 API。

你可能想知道如何看待这些 API。首先,它们是低级别的 API,是为低级别的代码和算法准备的。应用程序开发人员很少会用到这些。另一种思考这些 API 的方式类似于平台内部的 API,它们是用于 CPU 指令的低级别 .NET API。这些 API 是类似的,但它是为内存相关的操作暴露的低级别的 API。

6类库:System.Text.Json 序列化通知

System.Text.Json 序列化器现在将通知作为(反)序列化操作的一部分公开。它们对于默认值和验证非常有用。要使用它们,请在 System.Text.Json.Serialization 命名空间中实现一个或多个接口 IJsonOnDeserializedIJsonOnDeserializingIJsonOnSerialized 或 IJsonOnSerializing`。

这里有一个例子,在 JsonSerializer.Serialize()JsonSerializer.Deserialize() 中都进行验证,以确保 FirstName 属性不是 null

public class Person : IJsonOnDeserialized, IJsonOnSerializing
{public string FirstName{ get; set; }void IJsonOnDeserialized.OnDeserialized() => Validate(); // Call after deserializationvoid IJsonOnSerializing.OnSerializing() => Validate(); // Call before serializationprivate void Validate(){if (FirstName is null){throw new InvalidOperationException("The 'FirstName' property cannot be 'null'.");}}
}

以前,你需要实现一个自定义转换器来实现这一功能。

7类库:System.Text.Json 序列化属性排序

我们使用 System.Text.Json.Serialization.JsonPropertyOrderAttribute 特性增加了控制属性序列化顺序的能力,用一个整数指定了顺序,较小的整数先被序列化;没有该特性的属性有一个默认的排序值 0

这里有一个例子,指定 JSON 应该按照 Id, City, FirstName, LastName 的顺序进行序列化:

public class Person
{public string City { get; set; } // No order defined (has the default ordering value of 0)[JsonPropertyOrder(1)] // Serialize after other properties that have default orderingpublic string FirstName { get; set; }[JsonPropertyOrder(2)] // Serialize after FirstNamepublic string LastName { get; set; }[JsonPropertyOrder(-1)] // Serialize before other properties that have default orderingpublic int Id { get; set; }
}

以前,序列化顺序是由反射顺序决定的,而反射顺序既不是确定的,也不会导致特定的预期顺序。

8类库:System.Text.Json.Utf8JsonWriter

在用 Utf8JsonWriter 编写 JSON payloads 时,有时你需要嵌入“原始”JSON。

比如:

  • 我有一个设计好的字节序列,如下例所示。

  • 我有一个 blob,我认为它代表 JSON 内容,我想把它包起来,我需要确保包和它的内部保持良好的格式。

JsonWriterOptions writerOptions = new() { WriteIndented = true, };using MemoryStream ms = new();
using UtfJsonWriter writer = new(ms, writerOptions);writer.WriteStartObject();
writer.WriteString("dataType", "CalculationResults");writer.WriteStartArray("data");foreach (CalculationResult result in results)
{writer.WriteStartObject();writer.WriteString("measurement", result.Measurement);writer.WritePropertyName("value");// Write raw JSON numeric value using FormatNumberValue (not defined in the example)byte[] formattedValue = FormatNumberValue(result.Value);writer.WriteRawValue(formattedValue, skipValidation: true);writer.WriteEndObject();
}writer.WriteEndArray();
writer.WriteEndObject();

以下是对上述代码--特别是FormatNumberValue--的描述。为了提高性能,System.Text.Json 在数字为整数时省略了小数点/值,如 1.0。其理由是,写的字节数越少越好,有利于提高性能。在某些情况下,保留小数点可能很重要,因为消费者将没有小数点的数字视为整数,否则视为浮点数。这种新的“原始值”模型允许你在任何需要的地方拥有这种程度的控制。

9类库:JsonSerializer 同步流重载

我们为 JsonSerializer 添加了新的同步 API[17],用于将 JSON 数据序列化和反序列化到一个流。你可以在下面的例子中看到这个演示。

using MemoryStream ms = GetMyStream();
MyPoco poco = JsonSerializer.Deserialize<MyPoco>(ms);

这些新的同步 API 包括与新的 System.Text.Json source generator[18] 兼容和可用的重载,通过接受 JsonTypeInfo<T>JsonSerializerContext 实例。

10类库:System.Diagnostics Propagators

在过去的几年里,我们一直在改进对 OpenTelemetry[19] 的支持。实现该支持的一个关键点是确保所有需要参与遥测生产的组件以正确的格式输出到网络头。要做到这一点真的很难,特别是随着 OpenTelemetry 规范的变化。OpenTelemetry 定义了传播(propagation)[20]的概念来帮助解决这种情况。我们正在采用传播的方式来实现头的定制的一般模型。

关于更广泛的概念背景:

  • OpenTelemetry 规范 - 分布式跟踪数据结构的内存表示。

  • OpenTelemetry Span - 追踪构建块,在 .NET 中由 System.Diagnostics.Activity 表示。

  • W3C TraceContext - 关于如何通过众所周知的 HTTP 头传播这些分布式跟踪数据结构的规范。

下面的代码演示了使用传播的一般方法:

DistributedContextPropagator propagator = DistributedContextPropagator.Current;
propagator.Inject(activity, carrier, (object theCarrier, string fieldName, string value) =>
{// Extract the context from the activity then inject it to the carrier.
});

你也可以选择使用不同的传播器(propagator):

// Set the current propagation behavior to not transmit any distributed context information in outbound network messages.
DistributedContextPropagator.Current = DistributedContextPropagator.CreateNoOutputPropagator();

DistributedContextPropagator 抽象类决定了分布式上下文信息在网络传输时是否以及如何被编码和解码。编码可以通过任何支持字符串键/值对的网络协议进行传输。DistributedContextPropagator 以字符串键/值对的形式向载体注入数值并从载体中提取数值。通过添加对传播者的支持,我们实现了两件事。

  • 你不再需要使用 W3C 的 TraceContext 头文件。你可以编写一个自定义的传播器(甚至用你自己的头文件名称),而不需要 HttpClient、ASP.NET Core 等库对这种自定义格式有预先的了解。

  • 如果你实现了一个带有自定义传输的库(如消息队列),只要你支持发送和接收文本映射(如 Dictionary<string, string>),你现在可以支持各种格式。

大多数应用程序代码不需要直接使用这个功能,然而,如果你使用 OpenTelemetry,你很可能会在调用栈中看到它。一些库的代码如果关心跟踪和因果关系,可能会需要使用这个模型。

11类库:加密操作调用模式简化

.NET 的加密和解密部件是围绕着流设计的,没有真正的概念来定义什么时候有效载荷已经在内存中(already in memory)。SymmetricAlgorithm 上新的 Encrypt-Decrypt- 方法加速了 already in memory 的进展,目的是为调用者和代码审查者提供清晰的信息。此外,它们还支持从 span 中读取和写入。

新的简化方法为使用加密 API 提供了一个直接的方法:

private static byte[] Decrypt(byte[] key, byte[] iv, byte[] ciphertext)
{using (Aes aes = Aes.Create()){aes.Key = key;return aes.DecryptCbc(ciphertext, iv);}
}

在新的 Encrypt-Decrypt- 方法中,只使用 SymmetricAlgorithm 实例中的 Key 属性。新的 DecryptCbc 方法支持选择填充算法,但是 PKCS#7 经常与 CBC 一起使用,所以它是一个默认参数。如果你喜欢这种清晰的感觉,就指定它吧:

private static byte[] Decrypt(byte[] key, byte[] iv, byte[] ciphertext)
{using (Aes aes = Aes.Create()){aes.Key = key;return aes.DecryptCbc(ciphertext, iv, PaddingMode.PKCS7);}
}

你可以看到,现有的模式--使用 .NET 5--明显需要更多的管道来实现同样的结果:

private static byte[] Decrypt(byte[] key, byte[] iv, byte[] ciphertext)
{using (Aes aes = Aes.Create()){aes.Key = key;aes.IV = iv;// These are the defaults, but let's set them anyways.aes.Padding = PaddingMode.PKCS7;aes.Mode = CipherMode.CBC;using (MemoryStream destination = new MemoryStream())using (ICryptoTransform transform = aes.CreateDecryptor())using (CryptoStream cryptoStream = new CryptoStream(destination, transform, CryptoStreamMode.Write)){cryptoStream.Write(ciphertext, 0, ciphertext.Length);cryptoStream.FlushFinalBlock();return destination.ToArray();}}
}

12运行时:支持所有平台和架构的 W^X

运行时现在有一种模式,它不创建或使用任何同时可写和可执行的内存页。所有可执行的内存都被映射为只读不执行。这项功能在该版本的早期仅在 macOS 上启用--针对 Apple Silicon。在 Apple Silicon 机器上,禁止同时进行可写和可执行的内存映射。

这一功能现在在所有其他平台上被启用并支持。在这些平台上,可执行代码的生成/修改是通过单独的读写内存映射完成的,这对 JIT 代码和运行时生成的辅助程序都是如此。这些映射是在与可执行代码地址不同的虚拟内存地址上创建的,并且只在进行写入时存在非常短暂的时间。例如,JIT 现在生成代码到一个从头开始的缓冲区,在整个方法被 jitted 后,使用一个内存拷贝函数调用将其复制到可执行内存中。而可写映射的寿命只跨越了内存拷贝的时间。

这个新功能可以通过设置环境变量 DOTNET_EnableWriteXorExecute 为 1 来启用。这个功能在 .NET 6 中是可选的,因为它有一个启动时的退步(除了在 Apple Silicon 上)。在我们的 ASP.NET 基准测试中,当用 Ready To Run(R2R)编译时,退步了 ~10%。然而,在启用和未启用该功能的情况下,测得的稳态性能是一样的。对于启动性能并不重要的应用程序,我们建议启用该功能,因为它能提高安全性。我们打算作为 .NET 7 的一部分解决性能退步问题,届时默认启用该功能。

13结束

我们认为,我们已经到了新功能和改进已经完成的发布点。为团队点赞!

我们继续期待你们的反馈。我们将把 .NET 6 的其余部分放在完善(功能和性能)和新功能中发现的错误上。在大多数情况下,功能改进需要等到 .NET 7。请分享你的任何反馈,我们将很高兴对其进行分类。

感谢所有为 .NET 6 做出贡献的人,使其成为另一个伟大的版本。

感谢你成为一名 .NET 开发者。

文中相关链接:

[1].https://dotnet.microsoft.com/
[2].https://dotnet.microsoft.com/download/dotnet/6.0
[3].https://devblogs.microsoft.com/dotnet/announcing-net-maui-preview-7/
[4].https://devblogs.microsoft.com/aspnet/asp-net-core-updates-in-net-6-preview-7/
[5].https://devblogs.microsoft.com/dotnet/category/conversations/
[6].https://devblogs.microsoft.com/dotnet/string-interpolation-in-c-10-and-net-6/
[7].https://docs.microsoft.com/dotnet/core/compatibility/sdk/6.0/csharp-template-code
[8].https://docs.microsoft.com/dotnet/core/compatibility/sdk/6.0/implicit-namespaces
[9].https://docs.microsoft.com/dotnet/csharp/nullable-references
[10].https://github.com/dotnet/runtime/issues/29723
[11].https://twitter.com/JeffHandley/status/1424846146850131968
[12].https://github.com/jellyfin/jellyfin/blob/c07e83fdf87e61f30e4cca4e458113ac315918ae/Directory.Build.props#L5
[13].https://github.com/dotnet/roslyn/blob/main/docs/features/nullable-metadata.md
[14].https://github.com/dotnet/designs/blob/main/accepted/2021/preview-features/preview-features.md
[15].https://devblogs.microsoft.com/dotnet/preview-features-in-net-6-generic-math/
[16].https://github.com/dotnet/runtime/pull/54006
[17].https://github.com/dotnet/runtime/issues/1574
[18].https://devblogs.microsoft.com/dotnet/try-the-new-system-text-json-source-generator/
[19].https://devblogs.microsoft.com/dotnet/opentelemetry-net-reaches-v1-0/
[20].https://opentelemetry.lightstep.com/core-concepts/context-propagation/

.NET 6 预览版 7 发布--(最后一个预览版)相关推荐

  1. SQL Server 2005 - 如何在预存程序中调用另外一个预存程序

    要在一个预存程序中调用另外一个预存程序,可以使用下列两种方式之一进行调用:  <?xml:namespace prefix = o /> EXECUTE <欲执行之预存程序的名称&g ...

  2. 会声会影2023旗舰版终于发布啦!2023旗舰版新增功能介绍

    各位,大家好,万众期待会声会影2023旗舰版终于发布啦!我们先了解会声会影,会声会影(2023旗舰版是加拿大Corel公司制作的一款功能强大的视频编辑软件.大型视频制作软件.专业视频剪辑软件.会声会影 ...

  3. 手机安装linux发行版,最近发布新版本的Linux发行版汇总 - 2020-02-14

    最近一些发行版都进行了新版本发布,不论是使用最广泛的Ubuntu发行版还是鲜为人知的Tiny Core Linux,它们或是长期支持版本的安全更新,或是新版本的发布. 下面让我们一起来了解下近期这些发 ...

  4. DotNetBar for Windows Forms 12.7.0.10_冰河之刃重打包版原创发布-带官方示例程序版

    关于 DotNetBar for Windows Forms 12.7.0.10_冰河之刃重打包版 --------------------11.8.0.8_冰河之刃重打包版------------- ...

  5. DotNetBar for Windows Forms 12.5.0.2_冰河之刃重打包版原创发布-带官方示例程序版

    关于 DotNetBar for Windows Forms 12.5.0.2_冰河之刃重打包版 --------------------11.8.0.8_冰河之刃重打包版-------------- ...

  6. DotNetBar for Windows Forms 12.2.0.7_冰河之刃重打包版原创发布-带官方示例程序版

    关于 DotNetBar for Windows Forms 12.2.0.7_冰河之刃重打包版 --------------------11.8.0.8_冰河之刃重打包版-------------- ...

  7. Visual Studio 2022 预览版2 发布啦

    我们很高兴地宣布 Visual Studio 2022 的第二个预览版发布啦!预览版 1 是有史以来第一个 64 位 Visual Studio,提供了改进的可扩展性.从预览版 2 开始,我们专注于提 ...

  8. .NET MAUI 预览版 6 发布

    原文:bit.ly/2SKad9g 作者:.NET Blog - David 译者:精致码农 - 王亮 当我们还在从微软 Build 大会和 .NET 6 预览版 4 中缓过来的时候,我们在这里就开始 ...

  9. Visual Studio 2017 - Update 2预览版已发布

    微软在继续通过Visual Studio Preview项目测试各类新功能,同时会通过公开发布的正式版测试这些新功能在现实世界中的表现情况.通过这种方式,开发者有机会及时了解正在开发的新功能,在开发的 ...

最新文章

  1. 美团架构师开源5万字的《面试手册》PDF免费下载!
  2. CentOS下yum源epel扩展源
  3. 你可能不知道的Python面试秘籍 干货满满(附带参考答案)上篇
  4. Spring Data JPA 从入门到精通~事务的处理及其讲解
  5. 计算机自动关闭硬盘,你遇到过电脑硬盘自动关闭的问题吗?
  6. python输出24进制时间_python-如何在给定时间原点的情况下将日期时间从十进制转换为“%y-%m-%d%H:%M:%S”?...
  7. Swift - 控制流/控制结构说明(if,switch,for,while)
  8. VS Code 神器插件:代码一键运行,支持超过 40 种语言!
  9. 50个精心收集的惊人的jquery绚丽插件--功能全覆盖
  10. C语言中更改用户名,如何更改C:User/Administrator这个文件夹的名字
  11. JS代码对表格进行新增时无法解析HTML代码的解决方式
  12. 金蝶云php webapi,K/3 Cloud Web API销售出库单PHP完整示例【分享】
  13. html格式转换wps表格,用WPS Office轻松实现教案格式转换
  14. java发送lrc文件格式_基于java的lrc歌词文件解析工具
  15. 对Java语言入门初学者的一些建议
  16. rs485数据线接反_RS485引脚说明及接口说明
  17. ssm+Vue计算机毕业设计虚拟问诊系统(程序+LW文档)
  18. CSDN Markdown编辑器将公式取消斜体的方法
  19. [.NET基础]走进各种位运算
  20. DecimalFormat的用法介绍 --转载

热门文章

  1. javascript与xml实例应用
  2. C#为什么会这么慢之命运之终章-真理篇for firelong
  3. linux引导时输入特殊信息的含义
  4. php mysql insert 变量,php – 在blueimp / jquery-file-upload上添加更多自定义变量给mysql insert...
  5. Flask博客开发——Tinymce编辑器
  6. Java SpringMvc+hibernate架构中,调用Oracle中的sp,传递数组参数
  7. BZOJ1001 狼抓兔子 终于过了!
  8. 降低winnt Apache服务的权限,让你的虚拟主机更安全
  9. Cypher查询语言--Neo4j-WHERE(三)
  10. android bitmap drawable 互转