【问题标题】:Can I make Visual Studio warn me when I forget to assign String.Replace()?当我忘记分配 String.Replace() 时,我可以让 Visual Studio 警告我吗?
【发布时间】:2014-10-09 14:25:31
【问题描述】:

我刚刚写了下面这行 C# 代码,然后在程序没有按预期运行时花了几分钟的时间进行故障排除:

myString.Replace(oldValue, newValue);

myStringoldValuenewValue都是字符串变量。)

显然我的意图是让myString变量被重新分配一个等于原始myString值的新字符串,但oldValue子字符串被newValue替换。

同样明显(事后看来),那行代码不起作用,因为我应该将 Replace() 的返回值分配回 myString:

myString = myString.Replace(oldValue, newValue);

尽管我很清楚 C# 字符串是不可变的,因此编写了像 Replace() 这样的方法来返回一个新的字符串实例,但我仍然发现自己偶尔会不小心写出像上面的原始代码行这样的错误代码。

我的问题是:在这种情况下,我能否让 Visual Studio 给我一个编译时警告,让我不必在运行时手动查找和诊断问题?

请注意,由于我在此处使用 .Net 框架方法 (String.Replace),因此无法将相关方法重写为使用 out 参数(如 this similar question 中的参数)。

【问题讨论】:

  • 不同意这是重复的。所有答案都集中在编写代码上,这样您的代码就不会出现这些问题。这是关于从系统库中捕获问题。 FxCop 或 Resharper 实际上可以非常优雅地标记这些。
  • 你的耳朵之间应该有警报响起。一种明显改变 某些东西但不使用refout 参数调用的方法。你能找到的最便宜的工具。这个错误你也只犯过一次,大家都记得。
  • @HansPassant - 绝对,我同意,应该!不过,出于某种原因,这对我个人来说有点盲点——我只是在大约第三次发生这种情况(几个月后)之后才发布了这个问题。另外,一个反驳:一些方法(尽管在非原始类型上)确实会在没有 ref 或 out 的情况下更改它们的参数(并返回 void),例如 Array.Reverse 方法。
  • 实际上,我想一个更好的例子是改变被调用方法的对象的方法,比如 List.Add 方法。
  • @HansPassant “你也只犯过一次这个错误,每个人都记得。”为自己说话,十年来我一直在犯这个错误。如果没有 Resharper 令人难以置信的性能负担,编译器警告会非常好。

标签: c# visual-studio compiler-warnings


【解决方案1】:

您可以使用 ReSharper,当您不将返回值分配给变量时,它会给您一个警告,表明您忽略了方法的返回值。

【讨论】:

  • 感谢您的建议!不过,正如我在问题中提到的,我希望有一个免费的解决方案可用。
【解决方案2】:

have created a custom FxCop rule that handles this case for ignoring 调用不可变类型方法的结果。

基本要点是这样的:

/// <summary>
/// We need to find all Pop nodes, these are a member of the ExpressionStatement class.
/// After we find a Pop statement (which ignores the current value on the stack), we will see if the value added
/// to the stack is an instance MethodCall on an ImmutableType.
/// </summary>
/// <param name="statement"></param>
public override void VisitExpressionStatement(ExpressionStatement statement)
{
    if (statement == null) { throw new ArgumentNullException("statement"); }

    if (statement.Expression.NodeType == NodeType.Pop)
    {
        VisitUnaryExpression(statement.Expression as UnaryExpression);
    }
    base.VisitExpressionStatement(statement);
}

/// <summary>
/// When we've found the UnaryExpression we check it for a MethodCall on an ImmutableType
/// </summary>
/// <param name="unaryExpression"></param>
public override void VisitUnaryExpression(UnaryExpression unaryExpression)
{
    if (unaryExpression == null) { throw new ArgumentNullException("unaryExpression"); }

    if (unaryExpression.NodeType == NodeType.Pop)
    {
        MethodCall call = unaryExpression.Operand as MethodCall;
        if (call != null)
        {
            MemberBinding binding = call.Callee as MemberBinding;
            if (binding.BoundMember.DeclaringType != null
                && immutableTypes.Contains(binding.BoundMember.DeclaringType.FullName))
            {
                Method method = binding.BoundMember as Method;

                // If the method also returns an immutable Type we flag it as a problem.
                if (immutableTypes.Contains(method.ReturnType.FullName))
                {
                    this.Problems.Add(new Problem(GetResolution(), call));
                }
            }
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多