C# 中私有 const 变量和私有只读变量有区别吗?
题
拥有一个有什么区别吗? private const
变量或 private static readonly
C# 中的变量(除了必须分配 const
编译时表达式)?
由于它们都是私有的,因此不存在与其他库的链接。那么这会有什么不同吗?例如,它可以带来性能差异吗?内置字符串?有类似的吗?
解决方案
好吧,你可以在属性中使用consts,因为它们作为编译时存在。您无法预测静态只读变量的值,因为 .cctor
可以从配置等初始化它。
就使用而言,常量被烧入调用代码中。这意味着如果您重新编译库 dll来更改公共常量,但不更改消费者,那么消费者仍将使用原始值。使用只读变量,这不会发生。这样做的结果是常量(非常,非常轻微)更快,因为它只是加载值(而不是必须取消引用它)。
重新实习;尽管您可以手动执行此操作,但这通常是文字的编译器/运行时功能;如果你通过文字初始化一个只读字段:
someField = "abc";
然后 ldstr
。
其他提示
确实,这两种类型在初始化后就无法更改,但是它们之间有一些区别:
- 'const' 必须在声明的地方(编译时)进行初始化,而 'readonly' 可以在声明的地方或构造函数内部(ar 运行时)进行初始化。
例如 const 可以在这种情况下使用:
public class MathValues
{
public const double PI = 3.14159;
}
对于这种情况,只读会更好:
public class Person
{
public readonly DateTime birthDate;
public Person(DateTime birthDate)
{
this.birthDate = birthDate;
}
}
或者
public class Person
{
public readonly DateTime birthDate = new DateTime(1986, 1, 24);
}
“const”是静态的,因此它在该类的所有实例之间共享,并且可以直接访问(如 MathValues.PI),而“readonly”不是静态的。因此,像“static const”这样的声明是非法的,因为 const 是静态的,但“static readonly”是合法的
'const' 只能保存整型(sbyte、byte、short、ushort、int、uint、long、ulong、char、float、double、decimal、bool 或 string)、枚举或对 null 的引用(不是类或结构,因为它们是在运行时使用“new”关键字初始化的),而“readonly”可以保存复杂类型、结构或类(通过在初始化时使用 new 关键字),但不能保存枚举
有关常量的注意事项是它们实际存储在您的可执行文件中,因此声明其中很多将增加可执行文件的大小。
通常情况下,这不是一个大问题,但我的一位朋友在公司工作,强制执行“一切都必须是const”。规则并设法显着增加其编译的可执行文件大小。
以下是 C# .NET 之间的差异 常量, 只读 和 静态只读 字段(来自 本文).
常数:
- 默认静态
- 必须具有编译时值(即:你可以有“A”+“B”,但不能有方法调用)
- 可以用在属性中
- 被复制到使用它们的每个程序集中(每个程序集都会获取值的本地副本)
- 可以在函数内声明
只读实例字段:
- 创建实例时进行评估
- 构造函数退出时必须已设置值
静态只读字段:
- 当代码执行到达类引用时进行评估(即:创建新实例或执行静态方法)
- 静态构造函数完成时必须已评估值
- 您确实不想将 ThreadStaticAttribute 放在这些属性上(因为静态构造函数将仅在一个线程中执行,并且它将为其线程设置值;所有其他线程都将具有未初始化的该值)
C#.Net中的 const 和 readonly 字段之间存在显着差异
const默认是静态的,需要使用常量值进行初始化,以后不能修改。构造函数中也不允许更改值。它不能与所有数据类型一起使用。 对于前日期时间。它不能与DateTime数据类型一起使用。
public const DateTime dt = DateTime.Today; //throws compilation error
public const string Name = string.Empty; //throws compilation error
public readonly string Name = string.Empty; //No error, legal
readonly可以声明为static,但不是必需的。无需在声明时初始化。可以使用构造函数指定或更改其值。因此,它在用作实例类成员时具有优势。两个不同的实例化可能具有不同的只读字段值。 对于前 -
class A
{
public readonly int Id;
public A(int i)
{
Id = i;
}
}
然后,readonly字段可以使用即时特定值进行初始化,如下所示:
A objOne = new A(5);
A objTwo = new A(10);
这里,实例objOne的readonly字段值为5,objTwo的值为10.使用const不可能。
在使用中?并不是的。在编译时评估Consts,而在运行时评估readonly。您还可以在构造函数中为readonly变量赋值。
还有一件事。我在上面的评论中没有看到这一点,虽然我可能错过了它。你不能创建一个常量数组。
private const int[] values = new int[] { 1, 2, 3 };
但可以使用静态只读字段创建它。
private static readonly int[] values = new int[] { 1, 2, 3 };
因此,如果您需要一个数组常量,例如允许值列表,并且枚举不合适,那么静态只读是唯一的方法。例如,如果数组是可空的整数,如下所示:
private static readonly int?[] values = new int?[] { null, 1, 2, 3 };
不能那个有一个常数,可以吗?
不同之处在于静态只读字段的值是在运行时设置的,因此可以由包含类修改,而const字段的值设置为编译时常量。
在静态只读的情况下,允许包含类仅修改它
变量声明中的(通过变量初始值设定项) 在静态构造函数中(实例构造函数,如果它不是静态的) 如果const声明中不允许使用字段的类型,或者在编译时未知该值,则通常使用static readonly。
也允许实例只读字段。
请记住,对于引用类型,在两种情况下(静态和实例),只读修饰符仅阻止您为字段分配新引用。它特别不会使引用所指向的对象成为不可变的。
class Program
{
public static readonly Test test = new Test();
static void Main(string[] args)
{
test.Name = "Program";
test = new Test(); // Error: A static readonly field cannot be assigned to (except in a static constructor or a variable initializer)
}
}
class Test
{
public string Name;
}
不同之处在于静态只读可以由包含类修改,但const永远不能修改,必须初始化为编译时常量。要稍微扩展静态只读的情况,包含类只能修改它:
- 在变量声明中(通过变量初始值设定项)。
- 在静态构造函数中(实例构造函数,如果它不是静态的)。
C#.NET中的Const关键字
示例: public const string abc =“ xyz”;
仅在声明时初始化。
值在编译时计算,不能在运行时更改。
尝试更改它将导致编译错误。
Const已经是一种静态的。
由于类和结构在运行时使用new关键字初始化,因此您可以将常量设置为类或结构。但是,它必须是不可或缺的类型之一。
C#.NET中的只读关键字
示例: public readonly string abc;
可以在声明代码或consturctor代码中初始化。
在运行时评估值。
可以声明为静态或实例级属性。
只读字段可以在运行时使用new关键字来保存复杂对象。
Readonly字段可以在声明或类的构造函数中初始化。因此,只读字段可以根据使用的构造函数具有不同的值。
readonly成员也可以用于运行时常量,如下例所示:
public static readonly uint currentTicks = (uint)DateTime.Now.Ticks;
只读字段不隐式静态,因此静态关键字可以(必须)显式应用于只读字段(如果需要)。对于const字段,这是隐式静态的。
Readonly成员可以在初始化时使用 new关键字来保存复杂对象。