C# ';静态只读';与';常数';
我已经阅读了有关C# ';静态只读';与';常数';,c#,constants,C#,Constants,我已经阅读了有关const和static readonly字段的内容。我们有一些只包含常量值的类。它们用于我们系统中的各种事情。所以我想知道我的观察是否正确: 对于所有公共内容,这些常量值是否应始终为静态只读?并且仅对内部/受保护/私有值使用const 你推荐什么?我应该甚至不使用静态只读字段,而是使用属性吗?公共静态只读字段有点不寻常公共静态属性(只有一个get)更常见(可能有一个私有静态只读字段支持) const值直接烧入调用站点;这是一把双刃剑: 如果该值是在运行时获取的,可能是从配置中
const
和static readonly
字段的内容。我们有一些只包含常量值的类。它们用于我们系统中的各种事情。所以我想知道我的观察是否正确:
对于所有公共内容,这些常量值是否应始终为静态只读?并且仅对内部/受保护/私有值使用const
你推荐什么?我应该甚至不使用
静态只读
字段,而是使用属性吗?公共静态只读
字段有点不寻常<代码>公共静态属性(只有一个get
)更常见(可能有一个私有静态只读
字段支持)
const
值直接烧入调用站点;这是一把双刃剑:
- 如果该值是在运行时获取的,可能是从配置中获取的,那么它是无用的
- 如果更改常量的值,则需要重新生成所有客户端
- 但它可以更快,因为它避免了方法调用
- …有时可能已经被JIT内联了
为零
等,使常数合理;p除此之外,静态
属性更常见。需要注意的一点是const仅限于基本类型/值类型(字符串除外)。需要注意的几个相关事项:
const int a
- 必须初始化
- 初始化必须在编译时进行
- 可以使用默认值,无需初始化
- 初始化可以在运行时完成(编辑:仅在构造函数中)
如果我遇到了这个限制,那么我会退回到静态只读(static readonly),但有一个警告。正如Marc提到的,我通常会使用带有getter和backingprivate static readonly字段的公共静态属性。如果使用者位于不同的程序集中,我会使用
static readonly
。将const
和使用者放在两个不同的程序集中是一个很好的方法。只读关键字与const
关键字不同。const
字段只能在声明字段时初始化。readonly
字段可以在声明或构造函数中初始化。因此,readonly
字段可以具有不同的值,具体取决于所使用的构造函数。此外,虽然const
字段是编译时常量,但readonly
字段可用于运行时常量
Const:Const只不过是“常量”,一个值在编译时为常量的变量。必须给它赋值。默认情况下,常量是静态的,我们不能在整个程序中更改常量变量的值
静态只读:静态只读类型变量的值可以在运行时赋值,也可以在编译时赋值,并在运行时更改。但是这个变量的值只能在静态构造函数中更改。不能再改变了。它在运行时只能更改一次
参考资料:这只是对其他答案的补充。我将不再重复(四年后现在)
在某些情况下,常量和非常量具有不同的语义。例如:
const int y = 42;
static void Main()
{
short x = 42;
Console.WriteLine(x.Equals(y));
}
打印出True
,而:
static readonly int y = 42;
static void Main()
{
short x = 42;
Console.WriteLine(x.Equals(y));
}
写入False
原因是该方法有两个重载,一个重载接受short
(System.Int16
),另一个重载接受对象(System.object
)。现在的问题是,我的y
参数是否适用一个或两个
当y
是编译时常量(literal)时,const
情况下,如果int
是常量,则必须存在从int
到short
的隐式转换,并且前提是C#编译器验证其值是否在short
的范围内(即42
是)。请参见C语言规范中的。因此,必须考虑这两种重载。首选重载Equals(short)
(任何short
都是对象,但并非所有对象都是short
)。因此,将y
转换为short
,并使用该重载。然后,Equals
比较两个相同值的short
,得到true
当y
不是常数时,不存在从int
到short
的隐式转换。这是因为一般来说,int
可能太大,无法装入短的。(显式转换确实存在,但我没有说Equals((短)y)
,因此这不相关。)我们看到只有一个重载适用,Equals(object)
一个。因此,y
被装箱到对象
。然后,Equals
将比较System.Int16
和System.Int32
,由于运行时类型甚至不一致,这将产生false
我们得出结论,在某些(罕见的)情况下,将常量
类型成员更改为静态只读
字段(或其他方式,如果可能的话)可以更改程序的行为。常量
和只读
类似,但它们并不完全相同
const
字段是一个compi
struct Test
{
public const double Pi = 3.14;
public const int Zero = 0;
}
public class Color
{
public static Color Black = new Color(0, 0, 0);
public static Color White = new Color(255, 255, 255);
public static Color Red = new Color(255, 0, 0);
public static Color Green = new Color(0, 255, 0);
public static Color Blue = new Color(0, 0, 255);
private byte red, green, blue;
public Color(byte r, byte g, byte b) => (red, green, blue) = (r, g, b);
}
public class Color
{
public static readonly Color Black = new Color(0, 0, 0);
public static readonly Color White = new Color(255, 255, 255);
public static readonly Color Red = new Color(255, 0, 0);
public static readonly Color Green = new Color(0, 255, 0);
public static readonly Color Blue = new Color(0, 0, 255);
private byte red, green, blue;
public Color(byte r, byte g, byte b) => (red, green, blue) = (r, g, b);
}
public class A
{
public static const C = 0;
}
public class B
{
static void Main() => Console.WriteLine(A.C);
}
public const DateTime dt = DateTime.Today; //throws compilation error
public const string Name = string.Empty; //throws compilation error
public static readonly string Name = string.Empty; //No error, legal
public const decimal ProgramVersion = 2.3;
[HttpTrigger(AuthorizationLeve.Anonymous, HttpMethods.Get)] // COMPILE ERROR: static readonly,
[HttpTrigger(AuthorizationLeve.Anonymous, "GET")] // STRING
public class HttpConstants
{
public const string Get = "GET";
}
[HttpTrigger(AuthorizationLeve.Anonymous, HttpConstants.Get)] // Compile FINE!
private const int Total = 5;
private static readonly int GripKey = Animator.StringToHash("Grip");
private const int GripKey = Animator.StringToHash("Grip");