Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
编译时检测意外地将C#属性分配给自身_C# - Fatal编程技术网

编译时检测意外地将C#属性分配给自身

编译时检测意外地将C#属性分配给自身,c#,C#,Visual Studio C#编译器,但此警告不适用于C#属性,仅适用于变量。如中所述 然而,我真的希望类似的东西可以在编译时警告我,如果我将属性分配给它自己 我目前正在使用Visual Studio 2013,但如果该解决方案至少在Visual Studio 2015中起作用,我还可以。此外,我不使用第三方商业插件,如ReSharper或CodeRush,因此我更喜欢不涉及购买的解决方案,但我愿意接受建议 你知道我怎样才能做到这一点吗 背景: 我非常习惯使用readonlypublic存储接

Visual Studio C#编译器,但此警告不适用于C#属性,仅适用于变量。如中所述

然而,我真的希望类似的东西可以在编译时警告我,如果我将属性分配给它自己

我目前正在使用Visual Studio 2013,但如果该解决方案至少在Visual Studio 2015中起作用,我还可以。此外,我不使用第三方商业插件,如ReSharper或CodeRush,因此我更喜欢不涉及购买的解决方案,但我愿意接受建议

你知道我怎样才能做到这一点吗

背景: 我非常习惯使用readonlypublic存储接收到的依赖项的模式

例如,假设一个类
Foo
,它依赖于
ILogger
实现。
logger
实例提供给构造函数中的类,构造函数检查空值并将依赖项存储在名为
logger
的实例属性中:

public class Foo
{
    public ILogger Logger { get; private set; }

    public Foo(ILogger logger)
    {
        if(logger == null) throw new ArgumentNullException("logger");
        this.Logger = logger;
    }
}
但是,我经常犯键入错误,将属性分配给自身,而不是将参数传递给构造函数

public class Foo
{
    public ILogger Logger { get; private set; }

    public Foo(ILogger logger)
    {
        if(logger == null) throw new ArgumentNullException("logger");
        this.Logger = Logger; // <-- This is wrong. Property assigned to itself.
    }
}
公共类Foo
{
公共ILogger记录器{get;private set;}
公共Foo(ILogger记录器)
{
如果(logger==null)抛出新的ArgumentNullException(“logger”);

this.Logger=Logger;//这是VS2015实时代码分析器的理想情况。您可以编写一个基本分析器,检查属性是否分配给自身并创建错误

这里有一个很好的教程,我很早以前就遵循了它,它可以帮助你开始如何编写一个教程,它们不是很难做到:

更新:我有一些空闲时间,所以我写了一个分析器来做这件事

[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class SelfAssignmentAnalyzer : DiagnosticAnalyzer
{
    public const string DiagnosticId = "SelfAssignment";

    private static readonly LocalizableString Title = "Do not do self assignment";
    private static readonly LocalizableString MessageFormat = "The variable '{0}' is assigned to itself";
    private static readonly LocalizableString Description = "A variable assignment to itself is likely an indication of a larger error.";
    private const string Category = "Correctness";

    private static DiagnosticDescriptor Rule = new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, Category, DiagnosticSeverity.Warning, isEnabledByDefault: true, description: Description);

    public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get { return ImmutableArray.Create(Rule); } }

    public override void Initialize(AnalysisContext context)
    {
        context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.SimpleAssignmentExpression);
    }

    private void AnalyzeNode(SyntaxNodeAnalysisContext context)
    {
        var assignmentExpr = (AssignmentExpressionSyntax)context.Node;

        var right = context.SemanticModel.GetSymbolInfo(assignmentExpr.Right);
        var left = context.SemanticModel.GetSymbolInfo(assignmentExpr.Left);
        if (!right.Equals(left))
            return;

        var diagnostic = Diagnostic.Create(Rule, assignmentExpr.GetLocation(), assignmentExpr.Left.ToString());
        context.ReportDiagnostic(diagnostic);

    }
}
[DiagnosticanAnalyzer(LanguageNames.CSharp)]
公共类自分配分析器:DiagnosticanAnalyzer
{
public const string DiagnosticId=“SelfAssignment”;
private static readonly LocalizableString Title=“不进行自我分配”;
private static readonly LocalizableString MessageFormat=“变量{0}已分配给自身”;
private static readonly LocalizableString Description=“变量本身赋值可能表示存在较大错误。”;
private const string Category=“正确性”;
私有静态DiagnosticDescriptor规则=新的DiagnosticDescriptor(DiagnosticId、标题、消息格式、类别、DiagnosticSeverity.Warning、IsEnabled默认为true,描述为description);
公共覆盖ImmutableArray支持的诊断{get{return ImmutableArray.Create(Rule);}
公共覆盖无效初始化(AnalysisContext上下文)
{
RegisterSyntaxNodeAction(AnalyzeNode,SyntaxKind.SimpleAssignmentExpression);
}
专用void分析节点(SyntaxNodeAnalysisContext上下文)
{
var assignmentExpr=(AssignmentExpressionSyntax)context.Node;
var right=context.SemanticModel.GetSymbolInfo(assignmentExpr.right);
var left=context.SemanticModel.GetSymbolInfo(assignmentExpr.left);
如果(!right.Equals(left))
返回;
var diagnostic=diagnostic.Create(规则,assignmentExpr.GetLocation(),assignmentExpr.Left.ToString());
上下文。报告诊断(诊断);
}
}
您可以进行一些优化,不必调用
GetSymbolInfo
(例如,检查左侧和右侧的文本是否匹配),即可排除各种情况,但我将此作为练习留给您

编辑:

Visual Studio 2015内部运行的分析器:


更改键入参数的方式,以减少错误发生的频率

参数优先:

   public Foo(ILogger logger)
   { 
   }
下一步赋值:复制/粘贴参数两次

   public Foo(ILogger logger)
   { 
       // this.{paste} = {paste};
       this.logger = logger;
   } 
最后,更正拼写错误属性:

   public Foo(ILogger logger)
   { 
       this.Logger = logger;
   } 

然后尝试使用
专用ILogger\u logger
,不要认为logger必须是public@ScottChamberlain:我的想法是一样的,可能已经有了。@csharpfolk谢谢,我知道如果一个用户使用了一个字段,我会得到我在第一段中提到的警告,但这与C#properties的问题无关。另外,请检查关于检查属性的链接,根据定义,检查属性是公开的。请不要认为这是傲慢或固执:我知道我可以做出这些改变,但我真的很好奇这个特定场景的解决方案。很好的低技术建议。我不知道我是否会记得这样做,但我喜欢实用主义。谢谢。我怀疑这可能是答案之一,也许是“正确”的答案。但我想“众包”另一个答案(希望是聪明的)备选方案。如果没有其他选择,我会将其标记为已接受。众包如何制作分析仪本身:)谢谢!我目前没有VS2015实例,但会尽快尝试此分析仪。使其工作并添加屏幕截图。这正是我需要的。