C# 快速操作和重构

Visual Studio Code 为您提供了多种重构源代码的方法以及快速修复来生成代码并在编码时修复问题。要访问它们,请单击出现的“灯泡”图标或使用命令“快速修复”命令⌘。(Windows、Linux Ctrl+.显示快速修复和重构选项的列表。您还可以右键单击编辑器并选择Refactor ⌃⇧R(Windows、Linux Ctrl+Shift+R以仅显示重构选项。

支持的重构和快速修复

添加等待

内容:await关键字添加到函数调用中。

何时:当您在异步方法中调用函数时。

如何:

  1. 将克拉放在函数调用旁边(很可能会用红色下划线表示)。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 选择添加await

添加等待示例

从成员添加构造函数参数

内容:根据选定的类成员生成带有参数的新构造函数。

何时:您引入了一个新的构造函数,并希望使用所有正确的参数自动正确声明它。

原因:您可以在使用构造函数之前声明它,但是此功能会自动生成它。

如何:

  1. 突出显示要在构造函数中添加为参数的类成员。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 选择生成构造函数 <classname>(<membertype>, <membertype>, <etc.>)

从成员示例中添加构造函数参数

添加调试器显示属性

内容: DebuggerDisplay属性控制对象、属性或字段在调试器变量窗口中的显示方式。

何时:您希望在代码中以编程方式固定调试器内的属性。

原因:固定属性允许您通过将属性冒泡到调试器中对象属性列表的顶部来快速检查对象的属性。

如何:

  1. 将光标放在类型、委托、属性或字段上。
  2. ⌘。(Windows、Linux Ctrl+.触发“快速操作和重构”菜单并选择“添加DebuggerDisplay属性”
  3. DebuggerDisplay属性与返回 default 的 auto 方法一起添加ToString()

添加 DebuggerDisplay 属性示例

添加显式强制转换

内容:允许您根据使用情况自动向表达式添加显式转换。

何时:您需要向表达式添加显式强制转换,并希望自动正确分配它。

原因:您可以手动向表达式添加显式转换,但是此功能会根据代码上下文自动添加它。

如何:

  1. 将插入符号放在错误上。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 选择添加显式转换

添加文件头

内容:使用EditorConfig将文件头添加到现有文件、项目和解决方案。

何时:您想要轻松地将文件头添加到文件、项目和解决方案中。

原因:出于版权目的,您的团队要求您包含文件头。

如何:

  1. 如果您还没有EditorConfig,请将其添加到项目或解决方案中。
  2. 将以下规则添加到您的 EditorConfig 文件中:file_header_template.
  3. 将规则的值设置为等于您要应用的标题文本。您可以用作{fileName}文件名的占位符。
  4. 将插入符号放在任何 C# 文件的第一行。
  5. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  6. 选择添加文件头

添加缺少的使用/导入

内容:让您立即添加必要的导入或使用指令来复制和粘贴代码。

何时:通常的做法是从项目或其他来源的不同位置复制代码并将其粘贴到新代码中。此快速操作会查找复制粘贴代码中缺少的导入指令,然后提示您添加它们。此代码修复还可以添加项目之间的引用。

原因:由于快速操作会自动添加必要的导入,因此您无需手动复制代码所需的 using 指令。

如何:

  1. 从文件复制代码并将其粘贴到新文件中,而不包含必要的 using 指令。由此产生的错误伴随着代码修复,添加了缺少的 using 指令。
  2. 选择⌘。(Windows、Linux Ctrl+.打开“快速操作和重构”菜单。
  3. 选择使用 <您的参考>添加缺少的参考。

添加缺失/导入示例

添加命名参数

内容:将命名参数附加到函数调用中的指定参数值。

何时:如果您的方法带有很多参数,则可以添加命名参数以使代码更具可读性。

如何:

  1. 将光标置于函数调用中的参数上。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 选择添加参数名称 <参数名称>

添加命名参数示例

将匿名类型转换为类

内容:将匿名类型转换为类。

何时:您有一个匿名类型,希望在类中继续构建它。

原因:如果您仅在本地使用匿名类型,那么它们非常有用。随着代码的增长,最好有一种简单的方法将它们提升为类。

如何:

  1. 将光标置于匿名 ( var) 类型上。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 选择转换为类

将匿名类型转换为类示例

自动属性和完整属性之间的转换

内容:在自动实现的属性与完整属性之间转换。

何时:属性的逻辑发生了变化。

原因:您可以手动将自动实现的属性转换为完整属性,但是此功能会自动为您完成这项工作。

如何:

  1. 将光标放在属性名称上。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 从以下两个选项中进行选择:

选择转换为完整属性。

转换为完整属性示例

选择使用自动属性。

使用自动属性示例

在直接转换和“as”表达式之间转换

内容:使用关键字在常规强制转换和 try 强制转换之间转换变量as

何时:当您预计在某些情况下强制转换会失败时 ( as) 或您从未预计强制转换会失败(直接强制转换)。

如何:

  1. 将光标放在变量上。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 从以下两个选项中进行选择:

选择更改为投射

更改为演员示例

选择更改为as表达式。

更改为表达式示例

for 循环和 foreach 语句之间的转换

内容:如果代码中有for循环,则可以使用此重构将其转换为foreach语句。

原因:您可能希望将 for 循环转换为 foreach 语句的原因包括:

  • 除了作为访问项目的索引之外,不要在循环内使用局部循环变量。
  • 您希望简化代码并减少初始化程序、条件和迭代器部分中出现逻辑错误的可能性。

您可能希望将 foreach 语句转换为 for 循环的原因包括:

  • 您希望在循环内使用局部循环变量,而不仅仅是访问项目。
  • 您正在迭代多维数组,并且希望对数组元素进行更多控制。

如何:

  1. 将插入符号放在foreachorfor关键字中。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 从以下两个选项中进行选择:

选择转换为for

转换为示例

选择转换为foreach

转换成

Get 方法和属性之间的转换

将 Get 方法转换为属性

功能:允许您将 Get 方法转换为属性(以及可选的 Set 方法)。

何时:您有一个不包含任何逻辑的 Get 方法。

如何:

  1. 将光标置于 Get 方法名称中。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. (可选)如果你有Set方法,此时也可以转换你的Set方法。选择将 <Get 方法或 Set 方法名称> 替换为 property

用属性示例替换 Get 方法

将属性转换为 Get 方法

功能:允许您将属性转换为 Get 方法

何时:您的属性不仅仅涉及立即设置和获取值

如何:

  1. 将光标置于 Get 方法名称中。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 选择将 <属性名称> 替换为方法

将属性名称替换为方法示例

if 和 switch 语句之间的转换

内容:将语句转换ifswitch 语句或 C# 8.0 switch 表达式

何时:您想要将if语句转换为switch语句或switch表达式,反之亦然。

原因:如果您使用的是if语句,则此重构可以轻松过渡到 switch 语句或 switch 表达式。

如何:

  1. 将光标放在if关键字上。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 从以下选项中选择:

选择转换为switch语句

转换为语句示例

选择转换为switch表达式

转换为表达式示例

选择转换为if语句

转换为语句示例

在常规字符串和逐字字符串之间转换

内容:允许您在常规字符串和逐字字符串文字之间进行转换。

何时:您想要节省空间或使代码更加清晰。

原因:将逐字字符串文字转换为常规字符串文字有助于节省空间。将常规字符串文字转换为逐字字符串文字可以提供更多清晰度。

如何:

  1. 将插入符号放在常规字符串或逐字字符串文字上:
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 从以下选项之一中进行选择:

选择转换为常规字符串

选择转换为逐字字符串

将类转换为记录

内容:将您的类转换为 C# 记录。

何时:当您想要快速将类更改为记录时,该记录是为存储数据和不变性而定制的。

如何:

  1. 将光标放在类名称上。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 选择转换为位置记录

将类转换为示例之前的记录

示例后将类转换为记录

将局部函数转换为方法

内容:将本地函数转换为方法。

何时:您有一个想要在当前本地上下文之外定义的本地函数。

原因:您希望将本地函数转换为方法,以便可以在本地上下文之外调用它。当本地函数变得太长时,您可能需要转换为方法。当您在单独的方法中定义函数时,您的代码更易于阅读。

如何:

  1. 将光标置于本地函数中。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 选择转换为方法

将局部函数转换为方法示例

将数字文字转换为十六进制、十进制或二进制数

内容:在十六进制、二进制或十进制数之间转换数字。

何时:当您想要自动将数字转换为所需的基数而无需手动计算转换时使用。

如何:

  1. 将光标放在数字文字上。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 选择以下选项之一:

选择转换为十进制

转换为十进制示例

选择转换为十六进制

转换为十六进制示例

选择转换为二进制

转换为二进制示例

将占位符转换为内插字符串

内容:将格式化结果字符串(或占位符)转换String.Format为内插字符串。

何时:当您想要快速插入字符串时使用。

原因:插值字符串可以为您提供更具可读性的版本String.Format,并且可以让您直接访问变量名称。

如何:

  1. 将光标放在String.Format占位符上。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 选择转换为内插字符串

将占位符转换为内插字符串示例

将常规字符串转换为插值字符串

内容:将常规字符串更改为内插字符串。

何时:当您想要清理代码并使其更具可读性时使用。

如何:

  1. 将光标放在要转换的字符串上。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 选择转换为内插字符串

在示例之前转换为内插字符串

示例后转换为内插字符串

将元组转换为结构体

内容:将元组转换为struct

何时:当想要快速将元组更改为 astruct并且想要多次访问固定数据时使用。

如何:

  1. 将光标放在元组上。

  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。

  3. 选择以下选项之一:

    • 选择转换为struct-> 更新包含成员中的用法
    • 选择转换为struct-> 更新包含类型中的用法
    • 选择转换为struct-> 更新包含项目中的用法
    • 选择转换为struct-> 更新依赖项目中的用法

将元组转换为选项

将元组转换为示例

封装字段

内容:允许您将字段转换为属性,并更新该字段的所有用法以使用新创建的属性。

何时:您想要将字段移动到属性中,并更新对该字段的所有引用。

原因:您想要授予其他类访问某个字段的权限,但不希望这些类能够直接访问。例如,通过将字段包装在属性中,您可以编写代码来验证所分配的值。

如何:

  1. 将光标放在要封装的字段名称内。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 选择以下选项之一:

选择封装字段:<fieldname>(并使用属性)

封装字段并使用属性示例

选择封装字段:<fieldname>(但仍使用字段)

封装字段但仍使用字段示例

生成比较运算符

内容:允许您为实现的类型生成比较运算符IComparable

何时:IComparable您有一个实现我们将自动添加比较运算符的类型。

原因:如果您正在实现值类型,则应考虑重写该Equals方法,以获得比该Equals方法的默认实现更高的性能ValueType

如何:

  1. 将光标放在类内部或 IComparable 关键字上。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 从下拉菜单中选择生成比较运算符。

生成默认构造函数

功能:让您立即生成类上新的默认构造函数的代码。

何时:您引入了一个新的默认构造函数并希望自动正确声明它。

原因:您可以在使用构造函数之前声明它,但是此功能会自动生成它。

如何:

  1. 将光标放在类名称上。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 选择生成构造函数 <classname>()

生成默认构造函数示例

生成参数

内容:自动生成方法参数。

何时:您在当前上下文中不存在的方法中引用变量并收到错误;您可以生成一个参数作为代码修复。

原因:您可以快速修改方法签名而不会丢失上下文。

如何:

  1. 将光标置于变量名称上。
  2. ⌘。(Windows、Linux Ctrl+.触发“快速操作”和“重构”菜单。
  3. 选择生成参数

生成参数示例

明确实施所有成员

内容:在类中显式定义接口的方法。显式接口实现是仅通过指定接口调用的类成员。

何时:使用何时:

  • 您不希望为多个接口调用相同的实现。
  • 您想要解决两个接口各自声明同名的不同成员(例如属性和方法)的情况。

如何:

  1. 将光标放在类中正在实现的接口上。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 选择显式实施所有成员

显式实现所有成员示例

隐式实现所有成员

内容:在类中隐式定义接口的方法。隐式接口实现是指接口的方法和属性作为公共方法直接添加到类中。

如何:

  1. 将光标放在类中正在实现的接口上。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 选择实现接口

隐式实现所有成员

内联方法

内容:内联方法重构。

何时:您想要使用删除原始方法声明的选项来替换单个语句主体中静态、实例和扩展方法的使用。

原因:此重构提供了更清晰的语法。

如何:

  1. 将插入符号放在该方法的使用上。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 从以下选项之一中进行选择:

选择Inline <QualifiedMethodName>以删除内联方法声明:

内联方法示例

选择Inline 并保留 <QualifiedMethodName>以保留原始方法声明:

内联和保持方法示例

内联临时变量

功能:允许您删除临时变量并用其值替换它。

何时:使用临时变量会使代码更难理解。

原因:删除临时变量可能会使代码更易于阅读。

如何:

  1. 将光标置于要内联的临时变量内。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 选择内联临时变量

内联临时变量示例

为表达式引入局部变量

功能:让您立即生成局部变量来替换现有表达式。

何时:如果您的代码位于局部变量中,则以后可以轻松地重用该代码。

原因:您可以多次复制并粘贴代码以在不同位置使用它,但是最好执行一次操作,将结果存储在局部变量中,并始终使用局部变量。

如何:

  1. 将插入符号放在要分配给新局部变量的表达式上。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 从以下选项中选择:

选择引入本地 -> 为 <表达式> 引入本地

引入local for表达式示例

对于所有出现的 <表达式>选择引入本地 -> 引入本地

介绍参数

内容:让您立即生成新参数来替换现有表达式。

何时:如果您的代码位于参数中,则以后可以轻松地重用该代码。

原因:您可以多次复制并粘贴代码以在不同位置使用它,但是最好执行一次操作,将结果存储在参数中,并在整个过程中使用该参数。

如何:

  1. 将插入符号放在要分配给新参数的表达式上。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 从以下选项中选择:

选择<表达式>引入参数 -> 并直接更新调用站点

直接更新调用站点示例

选择将 <表达式> 的参数引入 -> 到提取的方法中

将参数引入提取的方法示例中

选择将 <表达式> 的参数引入 -> 到新的重载中

将参数引入新的重载示例

介绍using声明

内容:向您的实例添加using语句/代码块IDisposable

何时:IDisposable您想要确保正确获取、使用和处置一个实例。

如何:

  1. 将插入符号放在要分配给新参数的表达式上。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 选择引入using语句

引入语句示例

反转条件表达式和逻辑运算

内容:允许您反转条件表达式或条件and\or运算符。

何时:您有一个条件表达式或条件and\or运算符,如果将其反转会更好理解。

原因:手动反转表达式或条件and\运算符可能需要更长的时间,并且可能会引入错误。or此代码修复可帮助您自动进行此重构。

如何:

  1. 将光标置于条件表达式或条件and\or运算符中。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 选择条件反转替换&&||

反转条件示例

替换为示例

反转如果

What:允许您反转iforif else语句而不改变代码的含义。

何时:当你有一个iforif else语句,颠倒过来会更好理解时。

原因:手动反转ifor语句可能需要更长的时间,并且可能会引入错误。if else此代码修复可帮助您自动进行此重构。

如何:

  1. 将光标置于iforif else语句中。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 选择反转if

反转示例

使成员静态

内容:使成员静态。

何时:您希望非静态成员是静态的。

原因:静态成员提高了可读性:知道特定代码是隔离的,可以更容易理解、重读和重用。

如何:

  1. 将插入符号放在成员姓名上。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 选择设为静态

制作成员静态示例

将声明移至引用附近

作用:让您将变量声明移至更接近其用法的位置。

何时:您的变量声明可以在更窄的范围内。

原因:您可以保持原样,但这可能会导致可读性问题或信息隐藏。这是重构以提高可读性的机会。

如何:

  1. 将光标置于变量声明中。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 选择将声明移至引用附近

将声明移至参考示例附近

将类型移至匹配文件

内容:允许您将选定的类型移动到具有相同名称的单独文件中。

何时:您想要在同一个文件中分离多个类、结构、接口等。

原因:将多个类型放在同一个文件中可能会导致查找这些类型变得困难。通过将类型移至具有相同名称的文件,代码将变得更具可读性且更易于导航。

如何:

  1. 将光标置于定义该类型的类型名称内。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 选择将类型移动到 <typename>.cs

将类型移至匹配文件示例

反转 for 语句

内容:让您反转for语句。

When:当您想要反转for语句的含义及其迭代方式时使用。

原因:for手动反转语句可能需要更长的时间,并且可能会引入错误。此代码修复可帮助您自动进行此重构。

如何:

  1. 将光标置于for语句中。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 选择反向for语句

反向语句示例

拆分或合并 if 语句

内容:拆分或合并if语句。

何时:您想要将if使用&&or||运算符的语句拆分为嵌套if语句,或将if语句与外部if语句合并。

原因:这是风格偏好的问题。

如何:

如果你想拆分if语句:

  1. 将光标置于or运算符if的语句中。&&||
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 选择拆分为嵌套if语句

拆分为嵌套语句示例

如果要将内部if语句与外部if语句合并:

  1. 将光标放在内部if关键字上。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 选择与嵌套if语句合并。

与嵌套语句合并示例

使用显式类型

内容:var使用此重构将局部变量声明替换为显式类型。

原因:为了提高代码的可读性或者当您不想在声明中初始化变量时。

但是,当使用匿名类型初始化变量并且稍后访问该对象的属性时,必须使用var 。有关详细信息,请参阅隐式类型局部变量 (C#)

如何:

  1. 将插入符号放在var关键字上。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 选择使用显式类型而不是var

使用显式类型而不是示例

使用隐式类型

内容:使用此重构将局部变量声明中的显式类型替换为var.

原因:为了适应您的个人编码约定并显示更少的代码。当使用匿名类型初始化变量并且稍后访问对象的属性时,必须使用Var 。有关详细信息,请参阅隐式类型局部变量 (C#)

如何:

  1. 将插入符号放在显式类型关键字上。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 选择使用隐式类型

使用隐式类型示例

使用 lambda 表达式或块体

内容:允许您重构 lambda 表达式以使用表达式主体或块主体。

何时:您更喜欢 lambda 表达式使用表达式主体或块主体。

原因:可以根据您的用户偏好重构 Lambda 表达式以提高可读性。

如何:

  1. 将光标放在 lambda 运算符的右侧。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 选择以下选项之一:

选择对 lambda 表达式使用块体

使用块体作为 lambda 表达式示例

选择对 lambda 表达式使用表达式主体

使用 lambda 表达式的表达式主体

使用递归模式

内容:将代码块转换为使用递归模式。此重构适用于 switch 语句、属性模式匹配、元组模式匹配和位置模式匹配。

何时:使用递归模式可以使您的代码更具可读性/更简洁。

如何:

  1. 将光标放在要转换为递归模式的表达式上。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 选择以下选项之一:

选择switch语句转换为表达式

将语句转换为表达式示例

选择使用递归模式

在示例之前使用递归模式

在示例之后使用递归模式

换行、缩进和对齐重构

环绕并对齐调用链

功能:允许您包装和对齐方法调用链。

何时:您有一条长链,在一个语句中包含多个方法调用。

原因:当根据用户偏好进行换行或缩进时,阅读长列表会更容易。

如何:

  1. 将光标置于任意调用链中。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 选择“包裹调用链”“包裹并对齐调用链”以接受重构。

换行并对齐调用链示例

换行、缩进和对齐参数或参数

功能:允许您换行、缩进和对齐参数或参数。

何时:您有一个具有多个参数或参数的方法声明或调用。

原因:当参数或参数根据用户偏好进行换行或缩进时,读取一长串参数或参数会更容易。

如何:

  1. 将光标置于参数列表中。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 从以下选项中选择:

选择包裹每个参数 -> 对齐包裹的参数

对齐包装参数示例

选择环绕每个参数 -> 缩进所有参数

缩进所有参数示例

选择包裹每个参数 -> 缩进包裹参数

缩进参数示例

换行二进制表达式

内容:允许您包装二进制表达式。

何时:您有一个二进制表达式。

原因:当二进制表达式按照用户偏好包装时,读取它会更容易。

如何:

  1. 将光标置于二进制表达式中。
  2. ⌘。(Windows、Linux Ctrl+.触发快速操作和重构菜单。
  3. 选择换行表达式以接受重构。

换行表达式示例