请考虑以下代码:
class C
{
public int A { get; set; }
public int B;
public C(int a, int b)
{
this.A = A; // Oops, bug! Should be `this.A = a`. No warning
this.B = B; // Oops, bug! Should be `this.B = b`. `warning CS1717: Assignment made to same variable; did you mean to assign something else?`
}
}
A
和B
几乎完全相同,但有一个我会错过的错误。
有没有办法在编译时抓住第一个案例?
编辑:部分答案&评论想向我解释一下属性和字段不是一回事。我已经知道了。他们解释了为什么编译器在这里没有警告;我明白了。但是我写了一个bug,我不喜欢写错误。所以我的问题是“我怎样才能确保我永远不会再写这个错误了?”
答案 0 :(得分:6)
答案 1 :(得分:4)
你说A = A
和B = B
是一样的,但事实并非如此!您可以在propery的getter和setter中进行更改,以便A = A
可以更改变量,如下例所示:
public Int32 A
{
get { return _A++; }
set { _A = value; }
}
所以编译器不知道它是不是错误。当然,我会避免这种情况,因为它不是那么容易使用这样的代码(如果你只是有一个程序集,并且不知道为什么A每次都在改变),我会避免暴露这样一个明确的setter财产,喜欢下面的东西。
public UInt32 UniqueID { get { _UniqueID++; } }
public void Reset()
{
_UniqueID = 0;
}
编译时错误在这里没有任何意义,因为编译器不知道属性中发生了什么(记住:属性只是两种方法的简化,set_MyProperty和get_MyProperty ) ,如果属性发生变化(通过虚拟化),行为也可能会发生变化。
我以与您相同的方式编写属性和参数。例如,一个简单的类看起来如何:
public class MyClass
{
public Int32 Sample { get; private set; }
public MyClass(Int32 sample)
{
Sample = sample;
}
}
我每周都会和你一样陷入同样的陷阱〜大约1次,所以我从没想过要改变这些陷阱。但是你可以使用一些建议:
p
(参数)作为前缀,但这是我不推荐的,因为它使代码不可读恕我直言。value
作为后缀,这对我来说似乎没问题。因此,sample
代替sampleValue
而不是Sample
(属性名称),并且应该更容易检测是否使用属性名称而不是参数1 _
作为前缀。我不会使用它,因为我已经使用_
作为成员的前缀,以便能够快速访问它们并使智能感知看起来很奇怪恕我直言。我认为这完全取决于您的个人或公司编码风格,但我个人会使用Value
作为后缀。
答案 2 :(得分:4)
这不是铸铁,但如果您安装了ReSharper并将其“未使用参数”检查设置为“错误”,并进一步启用了解决方案范围分析,您会在代码窗口中看到:
右边缘的其中一个红色指标:
这在状态栏中显示:
它们共同构成一个组合,作为ReSharper用户,您很快就会无法忽视:)
不会阻止你编译。
答案 3 :(得分:4)
周杰伦,
一个很好的问题。我相信大多数相关的要点都已在各种回复中涵盖,但总结一下:
虽然可能不是你追求的答案,但我认为#3是最重要的一点。正确命名项目是最有效的解决方案。不仅如此,人们可能没有依赖ReSharper和其他此类工具的奢侈品。
为此,我还建议StyleCop。它可能有点侵入性,但它是一个很好的工具,可以帮助开发人员或开发团队遵守一套语法约定,你会发现这些约定会很快消除你突出显示的错误。< / p>
快乐的编码!
答案 4 :(得分:2)
除了上述所有答案之外,您还可以在项目属性中,在“构建”选项卡下,启用“将警告视为错误”,仅输入特定警告。如果您使用命令行编译器:
csc / warnaserror C.cs
csc / warnaserror:1717 C.cs
来自文档:http://msdn.microsoft.com/en-us/library/406xhdz3.aspx
这将使您的构建在所有警告或您指定的警告上失败。
答案 5 :(得分:1)
无序:
使用VB.NET
单元测试您的代码。
使用ReSharper并接受提示“Qualifer'this'is redundant” - 然后查找警告:Assignment made to same variable; did you mean to assign something else?
我看到了FxCop的建议,并认为Custom Code Analysis Rules using Introspection值得一提。
使用更好的变量名来识别参数与成员。这个提示当然不是高科技。我经常将变量与常量,数字或条件语句中函数的返回值进行比较。虽然读取起来稍微困难,但我习惯于在==运算符的左侧放置不能用作l值的操作数,忘记在==运算符中键入第二个等号将导致(非常明显的)编译器错误(五秒钟修复),而不是以后必须追踪逻辑错误(五分钟修复)。我觉得这一点与非常轻微的语法错误有关,这个错误只会让你陷入困境。
许多C#开发人员声明一个变量与类型名称相同,但小写的第一个字母除外。这种做法可能是你想要改变的。
答案 6 :(得分:0)
为什么字段this.B = B;
的自我分配错误?因为它什么也没做。 this.B
和B
完全相同。
为什么属性this.A = A;
的自我分配没有错?因为A
的含义取决于它所代表的=
运营商的哪一方。考虑编译器如何看待此代码:
set_A(get_A());
这是两种不同方法的调用。如果你打电话给Foo(Bar());
,你认为这是一个警告吗?也没有编译器。在getter中更改后备存储并不好,但要考虑属性,计算读数的数量,或进行一些日志记录,或者放置任何其他逻辑。为什么编译器会警告你呢?
public int A
{
get
{
_log.Debug("Property A accessed by some user");
_readingsCount++;
// your logic goes here
return _a;
}
}