简体   繁体   English

如何用Roslyn中的var替换字符串变量?

[英]How do I replace a string variable with a var in Roslyn?

For local declarations like: string a = string.Empty; 对于本地声明,例如:string a = string.Empty;

How can I write a diagnostic to change it to: var a = string.Empty; 如何编写诊断程序以将其更改为:var a = string.Empty;

You can't. 你不能。 The var keyword tells the compiler to perform type inference, and with just var a; var关键字告诉编译器执行类型推断,并且只使用var a; the compiler doesn't have enough information to infer a type. 编译器没有足够的信息来推断类型。

You could however do any of the following 但是,您可以执行以下任何操作

var a = new String();
var b = String.Empty;
var c = "";

but this seems like more effort than it's worth. 但这似乎比它的价值更多的努力。

Edit for updated request: Why do you want to modify all the code to be declared with var? 编辑更新的请求:为什么要修改要使用var声明的所有代码? It compiles to the same IL anyway (trivially simple example): 无论如何,它编译为相同的IL(简单的例子):

// var a = String.Empty;
IL_0000:  ldsfld     string [mscorlib]System.String::Empty
IL_0005:  pop
// string b = String.Empty;
IL_0006:  ldsfld     string [mscorlib]System.String::Empty
IL_000b:  pop

I've put together a code fix with diagnostic. 我已经整理了一个带诊断的代码修复程序。 Here's the interesting parts: 这是有趣的部分:

Implementation of AnalyzeNode from ISyntaxNodeAnalyzer 从ISyntaxNodeAnalyzer实现AnalyzeNode

public void AnalyzeNode(SyntaxNode node, SemanticModel semanticModel, Action<Diagnostic> public void AnalyzeNode(SyntaxNode node, SemanticModel semanticModel, Action<Diagnostic> addDiagnostic, CancellationToken cancellationToken)
    {
        var localDeclaration = (LocalDeclarationStatementSyntax)node;
        if (localDeclaration.Declaration.Type.IsVar) return;
        var variable = localDeclaration.Declaration.Variables.First();
        var initialiser = variable.Initializer;
        if (initialiser == null) return;
        var variableTypeName = localDeclaration.Declaration.Type;
        var variableType = semanticModel.GetTypeInfo(variableTypeName).ConvertedType;
        var initialiserInfo = semanticModel.GetTypeInfo(variable.Initializer.Value);
        var typeOfRightHandSideOfDeclaration = initialiserInfo.Type;
        if (Equals(variableType, typeOfRightHandSideOfDeclaration))
        {
            addDiagnostic(Diagnostic.Create(Rule, node.GetLocation(), localDeclaration.Declaration.Variables.First().Identifier.Value));
        }
    }

This essentially looks at the types on both sides of the declaration and if they're the same (and the RHS isn't already var) then add a diagnostic. 这主要是查看声明两侧的类型,如果它们相同(并且RHS不是var),则添加诊断。

And here's the code for the Code Fix: 这是代码修复的代码:

public async Task<IEnumerable<CodeAction>> GetFixesAsync(Document document, TextSpan span, IEnumerable<Diagnostic> diagnostics, CancellationToken cancellationToken)
    {
        var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
        var diagnosticSpan = diagnostics.First().Location.SourceSpan;
        var declaration = root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf().OfType<LocalDeclarationStatementSyntax>().First();
        return new[] { CodeAction.Create("Use var", c => ChangeDeclarationToVar(document, declaration, c)) };
    }

private async Task<Document> ChangeDeclarationToVar(Document document, LocalDeclarationStatementSyntax localDeclaration, CancellationToken cancellationToken)
    {
        var root = await document.GetSyntaxRootAsync(cancellationToken);
        var variableTypeName = localDeclaration.Declaration.Type;
        var varTypeName = SyntaxFactory.IdentifierName("var").WithAdditionalAnnotations(Formatter.Annotation);
        var newDeclaration = localDeclaration.ReplaceNode(variableTypeName, varTypeName);            
        var newRoot = root.ReplaceNode(localDeclaration, newDeclaration);
        return document.WithSyntaxRoot(newRoot);
    }

This bit is nice and simple, just get var from the Syntax factory and switch it out. 这一点很简单,只需从Syntax工厂获取var并将其切换出来。 Note that var doesn't have it's own static method in the SyntaxFactory so instead is reference by name. 请注意,var在SyntaxFactory中没有自己的静态方法,因此它是按名称引用的。

The compiler can't infer the type from that. 编译器无法从中推断出类型。

You would need to use: 你需要使用:

var a = ""; // compiler can see that is type `string`:

or you can do: 或者你可以这样做:

string a;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM