来自设置的Const字符串

时间:2014-04-09 11:39:01

标签: c# settings const

我想从设置中设置一个const字符串。

如果我想在将来改变程序语言,这很容易; 只需要修改相应的设置!

尝试时:

private const string constString =   
              "-&" + Properties.Settings.Default.constStringText;  

我收到此错误:

The property or indexer 'Properties.Settings.Default'  
cannot be used in this context because it lacks the get accessor.  

有什么想法吗?

4 个答案:

答案 0 :(得分:2)

由于您打算将此作为可选方法参数的默认值,即:

public void Foo(string something = constString)
{
    //do something
}

constString 必须编译时常量。来自the MSDN page for "Named and Optional Arguments"

  

默认值必须是以下类型的表达式之一:

     
      
  • 一个常量表达式;

  •   
  • 新形式ValType()的表达式,其中ValType是值类型,例如枚举或结构;

  •   
  • 表单default(ValType),其中ValType是值类型。

  •   

因此,实际上无法在运行时从配置文件中读取值,然后将其用于可选参数

一种解决方法是将constString声明为readonly字段:

private readonly string constString =   
              "-&" + Properties.Settings.Default.constStringText; 

然后创建所需的可选参数,并为不使用该参数的方法创建包装重载。该重载依次调用旧方法,并在运行时解析默认值:

public void Foo(string something) //no longer optional
{
    //do something
}

public void Foo()
{
    Foo(constString); //calls the other overload with the default value
}

答案 1 :(得分:1)

99%的与错误命名空间相关的案例存在此错误。 您可能已经生成了一些使用Properties.Settings.Default

的课程

解决方案:检查该类文件中的命名空间。它必须与存储该特定设置的App.config(Web.config)中的标记名称相同。

答案 2 :(得分:1)

虽然Chris Sinclair’s answer(一个const成员必须具有值类型并且在编译时可以评估,所以使用readonly)是正确的,我想解释这些限制并回答隐含的问题编译器消息意味着什么,虽然令人失望的评论似乎只是编译器中的错误

错误消息

  

属性或索引器'Properties.Settings.Default'不能在此上下文中使用,因为它缺少get访问器。

此消息表明,通过添加getter(以及其他可能的东西)可以使表达式Properties.Settings.Default可接受 - 据我所知,这完全是错误的。毕竟,一方面,当提问者向我们保证 1 时,有一个吸气剂,而另一方面,正如克里斯所解释的那样,表达式无效的原因是在编译时无法评估 - 时间,永远不可能,因为它取决于运行时配置。

据推测,此消息适用于其他情况,并且此处已被误用。

1 我在MSVS 2013中也看到了这一点,当默认参数值引用具有getter的属性时 - 但至少它也报告了“默认参数值for '<parname>'必须是编译时常量“。

对值类型的限制

const成员和默认参数值对值类型的限制(如C#5.0语言规范,2012)似乎完全不可避免 ,但是其他语言设计决策的可理解后果。

  • 引用类型可以在编译时具有可评估的构造函数,但这不受支持;也许这是因为语言无法指示引用的对象是不可变的,甚至也没有指示引用类型对象的不变性概念。 (记住:对象的不可变引用不必是对不可变对象的引用!)
  • 引用static方法的委托值也可以在编译时被认为是完全确定的,绑定到不可变对象的那些值也支持这个概念。
  • 不可变数组作为常量值听起来相当容易支持。
  • 常量成员¹和(我相信)²默认参数值被指定为类的'interface'的一部分,因为它们的值是在编译时确定并使用该类硬编码为生成的代码。

解决问题

  • 您可以使用 static readonly constString代替const constString,以明确虽然价值不会改变,直到运行时,在课堂或对象初始化时才确定(如Chris的回答)。
  • 如果要将表达式用作可选参数的默认值,必须才能成为真正的编译时常量,为您提供两种可能:

    • 宣布过载,如Chris的回答,例如:

      Foo() { Foo(Default); } Foo(string s) { Bar(s); }

      • 这通常是更简单的解决方案,但是如果您有许多这样的参数,那么可能会混乱您的代码和接口,因此会有很多重载,所有这些都带有文档注释。
    • 使用null作为默认约定,并在您的方法中解释:

      Foo(string s = null) { Bar(s != null ? s : Default); }

      • 这显然只有在null不是Foo(string)支持的参数时才有效,并且在文档注释中一定要明确。
    • 或许:应用Optional属性,如以下问题:behaviour of Optional attribute

      Foo([Optional] string s) { Bar(etc.?); }

      • 我没有使用或研究过这个 - 文档似乎相当稀疏​​ - 但它似乎很棘手并且不会产生超过默认值= null,除非null可能是Foo(string)支持的参数{1}}。

参考

¹语言规范5.0§10.5.2.210.5.2.2 常量和static readonly字段的版本控制
²我记得读过这篇文章,但没有在语言规范中找到它。

答案 3 :(得分:0)

我最近遇到过这种情况,在搜索解决方案时,我偶然发现了这个页面。基于上面的例子,我能够像这样解决我的问题:

private static readonly String ConStr
 = string.Format("Data Source={0};Initial Catalog={1}; User ID={2}; Password={3};",
                 Properties.Settings.Default.DataSource,
                 Properties.Settings.Default.Catalog,
                 Properties.Settings.Default.UserID,
                 Properties.Settings.Default.Password);

只是想分享。