编译时的常量字段
Posted
技术标签:
【中文标题】编译时的常量字段【英文标题】:Constant field at compiletime 【发布时间】:2014-04-09 09:42:12 【问题描述】:在c#编译时有什么方法可以区分非常量字段和常量字段吗?
我目前正在开发 c# 代码分析 (FxCop) 规则来检查开发人员的代码是否存在命名不一致。
我一直在寻找一种只针对常量字段的方法。但是它们在编译时是如何声明的呢?有没有像一个标志(我一直在研究“HasDefault”,但这并没有给我太多信息)。
我正在使用 FxCop-API(FxCopSdk.dll 和 Microsoft.Cci.dll)。不使用反射。
总结:如何使用代码分析(FxCop)区分非常量字段和常量字段,以及如何定位常量。
【问题讨论】:
不太清楚你的意思 - 你是不是想通过反射来发现const int x = 10;
和 static readonly int x = 10;
之间的区别?
不,我不确定您是否熟悉 Visual Studio 中的代码分析(以前称为 FxCop)。这是一种根据各种规则(例如不正确的命名)检查编译代码的机制。欲了解更多信息:msdn.microsoft.com/en-us/library/3z0aeatx.aspx。我想知道的是如何使用这种机制来定位常量。
对我来说听起来更适合 StyleCop,我认为它已经做到了你想要的。私有变量/常量的命名不需要保留在编译的程序集中。
StyleCop 确实做到了这一点,但我被命令使用 FxCop 来实现这一点,因为这些规则不太容易被开发人员忽略。此机制还可以阻止程序编译,“强制”开发人员使用定义的标准。
@Jon Skeet:使用 FxCop API,没有反射。我也在原始问题中添加了这个,谢谢。
【参考方案1】:
进一步研究你提到的FxCop SDK,我发现了一个字段IsLiteral,它基本上意味着一个在编译时指定值的成员。
这对你有用吗?
例如
public class ClassFieldNamePrefixes : BaseIntrospectionRule
public ClassFieldNamePrefixes() :
base("ClassFieldNamePrefixes", "TutorialRules.TutorialRules",
typeof (ClassFieldNamePrefixes).Assembly)
public override ProblemCollection Check(Member member)
if (!(member.DeclaringType is ClassNode))
return this.Problems;
Field fld = member as Field;
if (fld == null)
return this.Problems;
if (fld.IsLiteral &&
fld.IsStatic &&
field.Flags.HasFlag(FieldFlags.HasDefault))
....
return this.Problems;
【讨论】:
我似乎找不到针对这些类型修饰符的方法。你知道我怎样才能瞄准他们吗? 我刚刚发现了同样的情况,添加了一个所有常量字段都有的通用标志。感谢您的帮助:) 如何将 IsStatic 与 IsLiteral 一起使用? 作为常量关键字使成员静态? 是的,您也可以添加它。但我也会添加 HasDefault 标志。您可以添加它以便我接受您的答案吗? :)【参考方案2】:如果我编译一些包含此类的程序集
namespace Foo
public static class Bar
public int Pointless()
const int Whatever = 1;
return Whatever;
Whatever
在课堂外无法访问。我认为,即使使用反射。事实上,它可能在 IL 中被简化掉了(这是猜想。)
Whatever
的名称纯属风格问题,对编译后的程序集没有影响。如果是 public
字段,例如
namespace Foo
public static class Bar
public const int Whatever = 1;
然后可以通过代码分析来分析名称。
鉴于公共非常量字段已被标记
CA1051: Do not declare visible instance fields
CA2211: Non-constant fields should not be visible
也许你实际上根本不需要区分。
【讨论】:
这实际上是我想要定位的领域。我应该在我的提问中更清楚,对不起!事实上,这确实改变了整个问题,真的很抱歉! 这是很好的信息,但它仍然不能回答我关于能够实际定位常量字段的问题。 @MatthijsL,我唯一能想到的就是反编译NonConstantFieldsShouldNotBeVisible
,看看作者是如何做到的。我在任何地方都看不到它的记录。
我确实这样做了,反编译规则并查看是什么。它使用(如回答)field.IsLiteral。此外,几乎没有关于代码分析(FxCop)的文档,在处理此类规则时,这可能是一个真正的错误。【参考方案3】:
我发现了一种针对常量的有点脏的方法。
使用以下将针对他们(但可能会产生误报):
Field field = member as Field;
if (field == null)
return null;
if (field.Flags.HasFlag(FieldFlags.HasDefault) && field.IsLiteral && Field.IsStatic)
// Your code here.
【讨论】:
以上是关于编译时的常量字段的主要内容,如果未能解决你的问题,请参考以下文章