如何在C#中将类实例声明为常量?

如何在C#中将类实例声明为常量?,c#,.net,constants,C#,.net,Constants,我需要实施以下措施: static class MyStaticClass { public const TimeSpan theTime = new TimeSpan(13, 0, 0); public static bool IsTooLate(DateTime dt) { return dt.TimeOfDay >= theTime; } } 时间是一个常数(严重的:-),就像π是一样,在我的例子中,从设置中读取它是没有意义的。我希望

我需要实施以下措施:

static class MyStaticClass
{
    public const TimeSpan theTime = new TimeSpan(13, 0, 0);
    public static bool IsTooLate(DateTime dt)
    {
        return dt.TimeOfDay >= theTime;
    }
}
时间
是一个常数(严重的:-),就像
π
是一样,在我的例子中,从设置中读取它是没有意义的。我希望它被初始化一次,并且永远不会改变


但是C#似乎不允许一个常量由一个函数(构造函数就是这样)初始化。如何克服这个问题?

常量必须是编译时常量,编译器不能在编译时计算构造函数。使用和使用


一般来说,我更喜欢在构造函数中初始化,而不是通过直接赋值,因为您可以控制初始化的顺序。

使用
只读
而不是
常量
可以初始化,并且在初始化之后不会修改。这就是你要找的吗

public static readonly TimeSpan theTime = new TimeSpan(13, 0, 0);
代码示例:

static class MyStaticClass
{
    static readonly TimeSpan theTime;

    static MyStaticClass()
    {
        theTime = new TimeSpan(13, 0, 0);
    }
}
发件人:

常数必须是值类型(sbyte, 字节,短,ushort,int,uint,长, ulong、char、float、double、decimal、, 或bool)、枚举、字符串 文本,或对null的引用

如果要创建对象,则必须以静态只读方式创建:

static class MyStaticClass
{
  public static readonly TimeSpan theTime = new TimeSpan(13, 0, 0);
  public static bool IsTooLate(DateTime dt)
  {
    return dt.TimeOfDay >= theTime;
  }
}
C#的
const
与C++的
const
含义不同。在C#中,
const
基本上用于定义文本的别名(因此只能用文本初始化)
readonly更接近您想要的,但请记住,它只影响赋值运算符(除非对象的类具有不可变的语义,否则对象实际上不是常量)。

您可以使用:

当字段声明包含只读修饰符时,指定给 声明引入的字段只能作为 声明或在同一类的构造函数中

示例(从链接的MSDN页面复制):


常量表示其值永远不能更改的静态成员。这意味着在编译时定义了一个常量值。
用以下语句:

    public const TimeSpan theTime = new TimeSpan(13, 0, 0);
违反了常量字段的两个公理:
  • 只有C#内置类型(不包括System.Object)可以声明为常量。
  • 必须在编译时求值

    问题中使用了TimeSpan类型,它不是内置(预定义)
    类型。这意味着csc.exe编译器无法识别它。
    如果使用内置C#类型(例如字符串),并且希望使用编译时值初始化常量成员,则仍然会出现错误: e、 g.

     public const string MyNumber = SetMyString();
     private string SetMyString()
     {
      return "test";
     }
    
    解决您可以通过以下方式声明成员的问题:

    如果要在运行时仅声明一次字段,请使用修饰符:

    public static readonly string MyNumber = SetMyString();
    private static string SetMyString()
    {
     return "test";
    }
    

    时间
    也应该是静态的。所以只有一个,上面的例子可以编译。为什么是构造函数?仅将成员描述为公共静态只读TimeSpan theTime=new TimeSpan(13,0,0)似乎有效(至少没有编译错误)。@pickypg-抱歉,我的错误-修复@伊万-我补充了一条评论。我个人不喜欢直接初始化,因为你需要搜索一个类来找出初始化的地方。将初始化始终放在构造函数中是一致的,您可以很容易地看到类的初始状态是什么。您还可以直接控制初始化的顺序。在一个普通的静态类中,可能没有太大的区别。但好的实践是好的实践,尤其是在边缘情况下。使用ctor进行成员初始化的最大好处是,您有机会在引发异常的上下文中捕获和处理异常。我在自己的代码中使用了这一点,但我的肛门保持个性知道,每次我这样做,我的应用程序的记忆中都有一个长期存在的对象。我有一个长时间运行的应用程序,它已经占用了太多的内存,这让我很烦恼。我希望有一个TimeSpan文本可以编译到我的代码中。另一种方法是使用常量int,将我的TimeSpan值转换为毫秒。。。但是math.Readonly并不是const的正确类比。相反,您可能希望使用静态只读,正如詹姆斯在下面的回答中提到的那样。@ashelvey我在寻找一种像OP一样的固定方法时找到了这个页面。在我的情况下,只读不起作用,静态也不起作用。我想在类属性的属性中使用它,这意味着我需要一个常量。(我没有投你反对票,因为这不太可能,但这是你得到一些的一个可能原因。)readonly static不适用于开关情况和默认参数。我们仍然需要常量。值得一提的是,
    静态只读
    字段可以通过反射进行更改,而
    常量
    不能。
     public const string MyNumber = SetMyString();
     private string SetMyString()
     {
      return "test";
     }
    
    static readonly
    
    public static readonly string MyNumber = SetMyString();
    private static string SetMyString()
    {
     return "test";
    }