常见快速操作

此主题的各个部分列出了同时适用于 C# 和 Visual Basic 代码的一些常见“快速操作” 。 这些操作是适用于编译器诊断或 Visual Studio 中的内置 .NET Compiler Platform 分析器的代码修复。

修复错误的操作

本节中的“快速操作”可修复会导致生成失败的代码中的错误。 当“快速操作”可用于修复一行代码中的错误时,边距中或红色波浪线下会显示一个带有红色“x”的灯泡图标。

Quick Actions error icon and menu

更正拼写错误的符号或关键字

如果在 Visual Studio 中意外拼错类型或关键字,此“快速操作”会自动更正拼写错误。 灯泡菜单“将‘<拼写错误的单词>’更改为‘<正确单词>’”中会显示这些项。 例如:

// Before
private viod MyMethod()
{
}

// Change 'viod' to 'void'

// After
private void MyMethod()
{
}
错误 ID 适用的语言
CS0103、BC30002 C# 和 Visual Basic

解决 git 合并冲突

借助这些快速操作,可以通过“接受更改”(即移除冲突的代码和标记)解决 git 合并冲突问题。

// Before
private void MyMethod()
{
    if (false)
    {

    }
}

// Take changes from 'HEAD'

// After
private void MyMethod()
{
    if (true)
    {

    }
}
错误 ID 适用的语言 支持的版本
CS8300、BC37284 C# 和 Visual Basic Visual Studio 2017 版本 15.3 及更高版本

删除不必要代码的操作

删除不必要的 using/Import

“删除不必要的 Using/Import” 快速操作将删除当前文件中任何未使用的 usingImport 指令。 选择此项后,将删除未使用的命名空间导入。

删除不必要的 cast

如果你将一种类型强制转换为另一种不需要强制转换的类型,“删除不必要的强制转换” 快速操作可删除不必要的强制转换。

// before
int number = (int)3;

// Remove Unnecessary Cast

// after
int number = 3;

删除未使用的变量

借助此快速操作,可以从代码中删除已声明但从未用过的变量。

// Before
public MyMethod()
{
    var unused = 8;
    var used = 1;
    return DoStuff(used);
}

// Remove unused variables

// After
public MyMethod()
{
    var used = 1;
    return DoStuff(used);
}
诊断 ID 适用的语言 支持的版本
CS0219、BC42024 C# 和 Visual Basic Visual Studio 2017 版本 15.3 及更高版本

从“默认”值表达式中删除类型

此快速操作从默认值表达式中删除值类型,并在编译器可推断出表达式类型时使用 默认文本

// Before
void DoWork(CancellationToken cancellationToken = default(CancellationToken)) { ... }

// Simplify default expression

// After
void DoWork(CancellationToken cancellationToken = default) { ... }
诊断 ID 适用的语言 支持的版本
IDE0034 C# 7.1+ Visual Studio 2017 版本 15.3 及更高版本

添加缺失代码的操作

在引用程序集、NuGet 包或解决方案的其他类型中为类型添加 using/import

位于解决方案其他项目中的 using 类型将自动显示快速操作,但其他类型的快速操作则需要从“工具”>“选项”>“文本编辑器”>“C#”或“Visual Basic”>“高级”选项卡中启用:

位于解决方案其他项目中的 using 类型将自动显示快速操作,但其他类型的快速操作则需要从“工具”>“选项”>“文本编辑器”>“C#”或“基本”>“高级”选项卡中启用:

  • 建议对引用程序集中的类型使用 using/import
  • 建议对 NuGet 包中的类型使用 using/import

启用后,如果使用当前未导入但引用程序集或 NuGet 包中存在的命名空间中的类型,则会创建 using 或 import 指令。

// Before
Debug.WriteLine("Hello");

// using System.Diagnostics;

// After
using System.Diagnostics;

Debug.WriteLine("Hello");
诊断 ID 适用的语言
CS0103、BC30451 C# 和 Visual Basic

添加缺少的 case/默认 case/二者

在 C# 中创建 switch 语句,或在 Visual Basic 中创建 Select Case 语句时,可使用代码操作自动添加缺少的 case 项、默认 case 语句或同时添加二者。

请考虑使用以下枚举和空 switchSelect Case 语句:

enum MyEnum
{
    Item1,
    Item2,
    Item3
}

...

MyEnum myEnum = MyEnum.Item1;

switch(myEnum)
{
}

使用“添加二者” 快速操作可填充缺少的案例,并添加默认案例:

switch(myEnum)
{
    case MyEnum.Item1:
        break;
    case MyEnum.Item2:
        break;
    case MyEnum.Item3:
        break;
    default:
        break;
}
诊断 ID 适用的语言 支持的版本
IDE0010 C# 和 Visual Basic Visual Studio 2017 版本 15.3 及更高版本

添加 null 参数检查

借助此快速操作,可以在代码中添加检查,从而指明参数是否为 null。

// Before
class MyClass
{
    public string MyProperty { get; set; }

    public MyClass(string myProperty) // cursor inside myProperty
    {
        MyProperty = myProperty;
    }
}

// Add null check

// After
class MyClass
{
    public string MyProperty { get; set; }

    public MyClass(string myProperty)
    {
        MyProperty = myProperty ?? throw new ArgumentNullException(nameof(myProperty));
    }
}
适用的语言 支持的版本
C# 和 Visual Basic Visual Studio 2017 版本 15.3 及更高版本

添加参数名称

// Before
var date = new DateTime(1997, 7, 8);

// Include argument name 'year' (include trailing arguments)

// After
var date = new DateTime(year: 1997, month: 7, day: 8);
适用的语言 支持的版本
C# 和 Visual Basic Visual Studio 2017 版本 15.3 及更高版本

添加大括号

“添加大括号”快速操作将单行 if 语句包含在大括号内。

// Before
if (true)
    return "hello,world";

// Add braces

// After
if (true)
{
    return "hello,world";
}
诊断 ID 适用的语言 支持的版本
IDE0011 C# Visual Studio 2017 及更高版本

添加修饰符并对其排序

这些快速操作通过对现有辅助功能修饰符排序和添加缺失的辅助功能修饰符来帮助整理修饰符。

// Before
enum Color
{
    Red, White, Blue
}

// Add accessibility modifiers

// After
internal enum Color
{
    Red, White, Blue
}
// Before
static private int thisFieldIsPublic;

// Order modifiers

// After
private static int thisFieldIsPublic;
诊断 ID 适用的语言 支持的版本
IDE0036 C# 和 Visual Basic Visual Studio 2017 版本 15.5 及更高版本
IDE0040 C# 和 Visual Basic Visual Studio 2017 版本 15.5 及更高版本

代码转换

将“if”构造转换成“switch”

借助此快速操作,可以将 if-then-else 构造转换成 switch 构造。

// Before
if (obj is string s)
{
  Console.WriteLine("obj is a string: " + s);
}

else if (obj is int i && i > 10)
{
  Console.WriteLine("obj is an int greater than 10");
}

// Convert to switch

// After
switch (obj)
{
  case string s:
    Console.WriteLine("Obj is a string: " + s);
    break;
  case int i when i > 10:
    Console.WriteLine("obj is an int greater than 10");
    break;
}
适用的语言 支持的版本
C# 和 Visual Basic Visual Studio 2017 版本 15.3 及更高版本

转换为内插字符串

类似于 String.Format 方法,内插字符串是使用嵌入式变量来表达字符串的一种简单方式。 此快速操作可识别何时需要将字符串连接在一起或使用 String.Format,然后将用法更改为内插字符串。

// Before
int num = 3;
string s = string.Format("My string with {0} in the middle", num);

// Convert to interpolated string

// After
int num = 3;
string s = $"My string with {num} in the middle";
适用的语言 支持的版本
C# 6.0+ 和 Visual Basic 14+ Visual Studio 2017 及更高版本

使用对象初始值设定项

借助此快速操作,可使用对象初始值设定项,无需调用构造函数并添加赋值语句行。

// Before
var c = new Customer();
c.Age = 21;

// Object initialization can be simplified

// After
var c = new Customer() { Age = 21 };
诊断 ID 适用的语言 支持的版本
IDE0017 C# 和 Visual Basic Visual Studio 2017 及更高版本

使用集合初始值设定项

借助此快速操作,可使用集合初始值设定项,而无需多次调用类的 Add 方法。

// Before
var list = new List<int>();
list.Add(1);
list.Add(2);
list.Add(3);

// Collection initialization can be simplified

// After
var list = new List<int> { 1, 2, 3 };
诊断 ID 适用的语言 支持的版本
IDE0028 C# 和 Visual Basic Visual Studio 2017 及更高版本

将自动属性转换为完整属性

借助此快速操作,可在自动属性与完整属性之间转换。

// Before
private int MyProperty { get; set; }

// Convert to full property

// After
private int MyProperty
{
    get { return _myProperty; }
    set { _myProperty = value; }
}
适用的语言 支持的版本
C# 和 Visual Basic Visual Studio 2017 版本 15.5 及更高版本

将程序块主体转换为 expression-bodied 成员

借助此快速操作,可将程序块主体转换为方法、构造函数、运算符、属性、索引器和访问器的 expression-bodied 成员。

//Before
class MyClass4
{
    private int _myProperty;

    public int MyProperty
    {
        get { return _myProperty; }
        set
        {
            _myProperty = value;
        }
    }

    public MyClass4(int myProperty)
    {
        MyProperty = myProperty;
    }

    public void PrintProperty()
    {
        Console.WriteLine(MyProperty);
    }
}

// Use expression body for accessors/constructors/methods

// After
class MyClass4
{
    private int _myProperty;

    public int MyProperty
    {
        get => _myProperty;
        set => _myProperty = value;
    }

    public MyClass4(int myProperty) => MyProperty = myProperty;

    public void PrintProperty() => Console.WriteLine(MyProperty);
}
诊断 ID 适用的语言 支持的版本
IDE0021-27 C# 6.0+ Visual Studio 2017 及更高版本

将匿名函数转换为本地函数

此快速操作将匿名函数转换为本地函数。

// Before
Func<int, int> fibonacci = null;
fibonacci = (int n) =>
{
    return n <= 1 ? 1 : fibonacci(n - 1) + fibonacci(n - 2);
};

// Use local function

// After
int fibonacci(int n)
{
    return n <= 1 ? 1 : fibonacci(n-1) + fibonacci(n-2);
}

将“ReferenceEquals”转换为“is null”

诊断 ID 适用的语言 支持的版本
IDE0041 C# 7.0+ Visual Studio 2017 版本 15.5 及更高版本

此快速操作建议尽可能使用模式匹配,而不是 ReferenceEquals 代码模式。

// Before
var value = "someString";
if (object.ReferenceEquals(value, null))
{
    return;
}

// Use 'is null' check

// After
var value = "someString";
if (value is null)
{
    return;
}
诊断 ID 适用的语言 支持的版本
IDE0039 C# 7.0+ Visual Studio 2017 版本 15。 及更高版本

引入模式匹配

此快速操作建议使用模式匹配以及 C# 中的强制转换和 null 检查。

// Before
if (o is int)
{
    var i = (int)o;
    ...
}

// Use pattern matching

// After
if (o is int i)
{
    ...
}
// Before
var s = o as string;
if (s != null)
{
    ...
}

// Use pattern matching

// After
if (o is string s)
{
    ...
}
诊断 ID 适用的语言 支持的版本
IDE0020 C# 7.0+ Visual Studio 2017 及更高版本
IDE0019 C# 7.0+ Visual Studio 2017 及更高版本

更改数字参数的基数

借助此快速操作,可以将数字文本从一种基本数制转换成另一种。 例如,可以将数字更改为十六进制或二进制格式。

// Before
int countdown = 2097152;

// Convert to hex

// After
int countdown = 0x200000;
适用的语言 支持的版本
C# 7.0+ 和 Visual Basic 14+ Visual Studio 2017 版本 15.3 及更高版本

将数字分隔符插入数字文本

借助此快速操作,可以将分隔符添加到数字文本值中。

// Before
int countdown = 1000000;

// Separate thousands

// After
int countdown = 1_000_000;
适用的语言 支持的版本
C# 7.0+ 和 Visual Basic 14+ Visual Studio 2017 版本 15.3 及更高版本

使用显式元组名称

此快速操作识别可以使用显式元组名称而不是项1、项2 等的位置。

// Before
(string name, int age) customer = GetCustomer();
var name = customer.Item1;

// Use explicit tuple name

// After
(string name, int age) customer = GetCustomer();
var name = customer.name;
诊断 ID 适用的语言 支持的版本
IDE0033 C# 7.0+ 和 Visual Basic 15+ Visual Studio 2017 及更高版本

使用推断名称

此快速操作指出何时可简化代码,以使用匿名类型中推断的成员名称或元组中推断的元素名称。

// Before
var anon = new { age = age, name = name };

// Use inferred member name

// After
var anon = new { age, name };
// Before
var tuple = (age: age, name: name);

// Use inferred tuple element name

// After
var tuple = (age, name);
诊断 ID 适用的语言 支持的版本
IDE0037 C# Visual Studio 2017 版本 15.5 及更高版本
IDE0037 C# 7.1+ Visual Studio 2017 版本 15.5 及更高版本

析构元组声明

借助此快速操作,可析构元组变量声明。

// Before
var person = GetPersonTuple();
Console.WriteLine($"{person.name} {person.age}");

(int x, int y) point = GetPointTuple();
Console.WriteLine($"{point.x} {point.y}");

//Deconstruct variable declaration

// After
var (name, age) = GetPersonTuple();
Console.WriteLine($"{name} {age}");

(int x, int y) = GetPointTuple();
Console.WriteLine($"{x} {y}");
诊断 ID 适用的语言 支持的版本
IDE0042 C# 7.0+ Visual Studio 2017 版本 15.5 及更高版本

使方法同步

如果对方法使用 asyncAsync 关键字,还应在相应方法中使用 awaitAwait 关键字。 不过,如果不是这种情况,则会显示快速操作,可用于删除 asyncAsync 关键字并更改返回类型,从而让方法变成同步方法。 从“快速操作”菜单中使用“使方法同步” 选项。

// Before
async Task<int> MyAsyncMethod()
{
    return 3;
}

// Make method synchronous

// After
int MyAsyncMethod()
{
    return 3;
}
错误 ID 适用的语言
CS1998、BC42356 C# 和 Visual Basic

使方法异步

如果你在方法内使用的是 awaitAwait 关键字,方法应标记有 asyncAsync 关键字。 不过,如果不是这种情况,便会看到让方法异步的快速操作。 从“快速操作”菜单中使用“使方法/函数异步” 选项。

// Before
int MyAsyncMethod()
{
    return await Task.Run(...);
}

// Make method asynchronous

// After
async Task<int> MyAsyncMethod()
{
    return await Task.Run(...);
}
错误 ID 适用的语言 支持的版本
CS4032、BC37057 C# 和 Visual Basic Visual Studio 2017 及更高版本

请参阅