在C#中实现全局常量的最佳方法是什么?

时间:2011-12-09 13:52:00

标签: c# asp.net resources constants readonly

我有一个Common项目,我在其中添加了QueryStringNames的公共常量。

我知道常量应该是内部或私有的,但我需要公共常量,因为我想允许全局访问查询字符串名称,会话密钥等。

我知道有3种解决方案,但它们都有一个重要问题。调用程序集将包含my常量的副本,这意味着如果我必须更改常量值,我将必须编译我的Common程序集和调用程序集程序。

1) public const string ConstName = "a value";
2) public readonly string ConstName = "a value";
3) To be stored in a public resource file.

除了将它们存储在web.config文件(没有intellisense)之外,在C#中定义公共常量的最佳方法是什么?

7 个答案:

答案 0 :(得分:6)

这取决于。如果它确实是一个不会改变的常量,即使在未来的代码版本中,那么const也没问题。否则请使用static readonly字段。

const将嵌入到调用程序集中,而static readonly调用程序集只包含对该字段的引用。这意味着const需要在更改值时重新编译所有相关代码,而public readonly即使不重新编译调用程序集也会使用新值。

如果要将“常量”存储在配置文件中,但是像Intellisense一样,则可以使用不带公共设置器的属性。然后在运行时从配置文件中填充它。但我认为首先配置值不应该是static。对于配置值,我会使用某种单独的单一格式,最好是IoC变体,而不是Class.Instance变体。所以我只需要定义如下界面:

interface IMyConfig
{
  string Key{get;}
}

并且需要此配置的类将其作为构造函数参数:

public MyClass(IMyConfig config)
{
    ...
}

答案 1 :(得分:6)

如果你认为你要改变它并且你担心必须编译它,那么为什么不在web配置文件中使用appSettings?这就是它的用途。如果你真的需要intellisense,那么你可以将一个类放在一个读取配置值的程序集中,并将其公开为一个属性,以便于引用。如果它是敏感数据,那么我不会把它放在配置文件中,我会编译它,因为你不想破坏你的应用程序。

<appSettings>
    <add key="myconstant" value="here's the value!" />
</appSettings>

这是引用该值的类,它为您提供智能感知,能够在将来轻松更改它,而无需重新编译任何内容

public class MyAppConfigSettings
{
    public string MyConstant { get; private set; }

    public MyAppConfigSettings()
    {
        MyConstant = ConfigurationManager.AppSettings["myconst"];
    }
}

它可能不是您的解决方案的答案,但它可能会给您一些其他想法。

答案 2 :(得分:2)

如果您正在激活fxCop(Visual Studio发行版中包含的代码分析工具),您可能会感到有兴趣将常量更改为:

  

public static readonly string ConstName =“a value”;

答案 3 :(得分:2)

我不确定我是否完全理解了这个问题...你是否要求一个解决方案来存储一些全局变量,这些变量不会导致重新编译引用那些全局变量的程序集,如果你改变它们?如果是这样,为什么不尝试按照Inversion of Control原则考虑重新设计您的架构?想“不要打电话给我们,我们会打电话给你”好莱坞原则。如果需要某个const的所有程序集只调用一个接口(它们拥有),它接受一个具有所需值的属性,然后你有一个实现这些接口的常量项目(通过引用那些项目然后实现这些接口)那么当你改变常量的值时,那些项目永远不需要重新编译。

我确定你知道它们但是读了SOLID principles,“D”是依赖性倒置原则(控制反转)。我认为考虑到你的担忧(假设我理解你的话),他们可以帮助你。

控制反转的一个例子可以简单如下:

MyService.dll:

public class MyService
{

    // injected dependency
    public IMyConstants MyConstants { get; set; }

    public MyMethod(){

        // get your query...
        var query = IMyConstants.Query;
    }

}

MyConstants.dll:

public MyConstants : IMyConstants {

    // implementation of query property from the myservices.dll interface
    public string Query { ... }

}

因此myconstants.dll引用myservice.dll而不是相反(意味着myservices不需要重新编译)。然后,引导代码(将其全部设置并注入依赖关系)存在于其他地方。

对不起,如果我误解了你,希望尽管有帮助!

答案 4 :(得分:0)

在大多数情况下,我更喜欢第二个选项,因为它不会导致问题(通过复制值到其他程序集)。速度可能比常数慢,但这种纳秒速度还不成熟。

答案 5 :(得分:0)

您可以使用Cache对象并在Global.asax中定义它们

答案 6 :(得分:0)

如前所述,情况并非如此:

  • const:除非重新编译,否则无法修改。
  • readonly:该值在声明或构造函数中初始化,并在之后保持只读。
  

当字段声明包含只读修饰符时,声明引入的字段的赋值只能作为声明的一部分或在同一类的构造函数中出现