为原生代码选择 C++ 或 C#
需要进行架构审查:本文档旨在支持针对 React Native 的“旧”或“遗留”架构的开发。它可能适用也可能不适用于新架构的开发,需要审查并可能需要更新。有关 React Native Windows 中 React Native 架构的信息,请参阅新旧架构。
有关 Windows 上原生开发的最新信息,请参阅原生平台:概述。
React Native for Windows 同时支持使用 C++ 和 C# 编写原生代码,但每种语言都有其权衡。语言的选择会影响项目的兼容性、开发人员体验和性能。因此,无论您是构建应用程序还是原生模块,都应该选择最符合您要求的原生语言。
注意:本文档中,C++ 特指 C++/WinRT。
常见考量
兼容性矩阵
虽然 React Native for Windows 工具链支持用这两种语言编写的应用程序和模块项目,但在混合使用这些项目时存在限制。
下表列出了几种兼容性场景,说明了用某种语言编写的应用程序是否可以消费用某种语言编写的模块。
- ✅ 表示该场景有效
- 🟨 表示该场景部分有效(即有特定限制)
- 🟥 表示该场景无效
C++ 应用程序 | C# 应用程序 | |
---|---|---|
C++ 模块 | ✅ | ✅ |
带有 C++ NuGet 依赖项的 C++ 模块 | ✅ | ✅ |
带有 C# NuGet 依赖项的 C++ 模块 | 🟥 | 🟥 |
C# 模块 | 🟨 | ✅ |
带有 C# NuGet 依赖项的 C# 模块 | 🟥 | ✅ |
带有 C++ NuGet 依赖项的 C# 模块 | 🟥 | ✅ |
因此,如果您正在编写一个应用程序,您需要问自己是否需要消费任何原生模块。如果需要,在决定应用程序的语言时,您需要仔细检查这些模块的语言。
现在,如果您正在编写一个原生模块,您需要问自己是否需要消费 NuGet 中的包。如果需要,在决定模块的语言时,您需要仔细检查这些包的语言。
最后,如果您有任何想要重用的现有原生(源)代码,您也需要将其考虑在内。
注意:我们正在积极修复阻碍这些场景的错误,并改进 C# 和 C++ 项目的混合使用。有关阻碍兼容性的实际错误的更多详细信息,请参阅问题 #6819。
开发人员体验
C# 开发为编写 Windows 原生代码带来了工程效率,包括
- 广泛的标准库
- 丰富的工具、库和代码示例生态系统
- 多种现代编码约定的语法选项
如果您是现有 Java 开发人员,或计划从 Android 移植现有 Java 代码,您可能会发现使用 C# 开发比使用 C++ 编写所需的精力更少。
然而 C++/WinRT 开发也提供了其自身的一系列优势
- 访问更广泛的可移植 C++ 代码生态系统
- 丰富的工具生态系统
- 完全控制内存管理
如果您是现有 C++ 开发人员,或计划使用现有 C++ 代码,您可能会发现使用 C++/WinRT 开发效率最高。
性能
通常,C++ 编写的代码运行速度更快,内存使用量也少于 C# 编写的代码。这是因为 C++ 可以更好地控制内存分配,并且 C++ 直接编译成目标平台(X86、X64、ARM 等)的原生机器码。而 C# 中,垃圾回收可能导致性能下降,并且 C# 即使最终编译成机器码(我们稍后会讲到这一点),它首先也会编译成中间语言 (IL)。
过去,C# 应用程序依赖于在运行时将 IL 即时 (JIT) 编译为机器码。这意味着 IL 会交付给最终用户机器,并且 JIT 过程直到用户运行应用程序时才发生,这可能会对应用程序的性能和启动时间产生负面影响。
然而,UWP 应用程序并非如此,它们默认使用 .NET Native 工具链。.NET Native 工具链(在构建应用程序的“Release”配置时启用)会在构建时将您的 IL 代码交叉编译为原生机器码。因此,当您将应用程序提交到 Microsoft 商店时,只有完成的“原生化”代码才会交付给最终用户机器。这提高了这些应用程序相对于非“原生化”应用程序的性能和启动时间。有关 .NET Native 应用程序性能的更多信息,请参阅使用 .NET Native 衡量启动改进。
最终,只有对实际代码进行适当的性能分析和测试,才能确定两种语言的性能差异是否显著和/或最终用户是否能察觉到。
对等性说明
最终,虽然我们努力在 C++ 和 C# 开发之间保持对等性,但它们各有优缺点,没有一种语言适用于所有场景。React Native for Windows 的核心和绝大部分本身就是用 C++/WinRT 编写的,目的是最大限度地提高性能并促进与其他平台(包括标准 React Native 和 React Native for macOS)上的项目共享 C++ 代码。
出于类似原因,微软开发人员更喜欢用 C++ 而不是 C# 为社区模块做贡献。
但是,如果您的应用程序或模块已经使用 C#,您应该继续使用 C#。