为什么没有关于身份分配的警告?

7

我曾经犯过这个错误很多次——当我工作紧张并使用代码自动完成时,就会发生这种情况。最终我得到了以下的代码:

public class Model : IModel
{
    public PropertyNames PropertyNames { get; set; }
    public Model(PropertyNames propertyNames)
    {
        PropertyNames = PropertyNames;
    }
}

之后,一个测试以不太明显的方式失败了,我感到很沮丧。

我只是好奇是否有合法的理由编写那样的代码,如果没有,那它是否适合生成警告?


我认为这种行为相当疯狂。我觉得,至少代码补全应该更加智能化。 - Domenic
顺便说一下,我通常会尽量避免出现属性名称与其类型相同的情况。例如:public PropertyNames Names { get; set; } - Eoin Campbell
2
你可能想阅读http://blogs.msdn.com/b/ericlippert/archive/2011/03/03/danger-will-robinson.aspx。 - Anthony Pegram
@Eoin,我同意使用相同的属性名称也违反了我的本能,但是当我注意到更有经验的开发人员这样做时,我开始这样做,随着时间的推移,我判断它对整体复杂性产生了累积的积极影响(附注:如果我们开始就此进行辩论,该线程将被关闭... :)) - Aaron Anodide
@Pegram,感谢您提供的参考资料。在他的例子中,错误导致堆栈溢出,因此不会发出警告的原因是“它会立即被捕获”-我在这里并不抱怨,但我遇到了一个情况,错误被稍微延迟地捕获了...我的属性具有其默认值(我想是null),并且事情的表现就像初始化失败了一样。 - Aaron Anodide
3个回答

6

我只是好奇是否有合理的原因编写这样的代码

从某种程度上来看,不幸的是是的。因为我们所谈论的标识符是一个属性,在属性中赋值给另一个属性看起来像是一个空操作,但实际上会调用方法,即getter和setter方法,这些方法可能会产生副作用。

一个非常常见的特定情况是,如果setter执行类似于属性通知或调用观察者的操作,但在调用getter或setter时可能发生任何事情。这就是为什么该代码不会生成警告的原因:因为这种编码风格实际上很有用并且在生产代码中使用。

编辑:

相比之下,如果标识符是一个字段而不是一个属性,则会生成以下警告:

警告CS1717:对同一变量进行的赋值;您是否要分配其他内容?


我很欣赏你在这里使用“不幸”的措辞。 - Marc.2377
顺便说一句,如果在分配给只读/自动属性时生成此警告,那就太棒了。 - Marc.2377

3
除了“它算作有效指令”之外,没有理由使用它。尽管如此,它也不是错的:它符合赋值的语法。
如果您正在编写代码验证器,则这是一个好的警告候选项,尽管当然不应该妨碍实际编译; 大多数编译器在字节码优化期间已经捕获此类操作,其中不执行任何控制逻辑并且不实际修改寄存器的指令将被删除。

离题了...在一般情况下,这种属性赋值并不能保证是nop:getter可能会触发各种副作用的操作,并且类的作者可能正在使用P = P赋值作为一种(疯狂的、迂回的、容易出错的)方式来从构造函数中触发这些操作。 - LukeH
@LukeH:不是离题,事实上这就是问题所在。 - Rick Sladkey
@LukeH,你当然是对的 - 我只想说它让我想起了一些东西,我认为这引起了我在C/C++时代的警告,而它所属的一般警告类别是“如果很容易因错误而编写,并且99%的时间它确实是一个错误,则生成警告”..我能想到的最简单的事情就是如果你在表达式中放置一个赋值,单个=而不是==...语言允许它,但开发人员很少打算这样做。 - Aaron Anodide

3
使用 FxCop(又称代码分析),它将给出警告:
警告 3 CA1801:Microsoft.Usage:'Model.Model(string)'的参数'propertyNames'从未被使用。删除该参数或在方法体中使用它。

我在投票规则上有点放松了,因为这个答案对我来说是最有用的答案,即使从字面上讲它并没有回答我的问题 :) 希望没问题。 - Aaron Anodide

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接