C#中私有const和私有只读变量之间有区别吗?

在C#中使用private const变量或private static readonly变量之间是否有区别(除了必须为const分配编译时表达式)?

由于它们都是私有的,因此没有与其他库的链接。 它会有什么不同吗? 例如,它可以产生性能差异吗? 实习字符串? 有什么相似的吗?

好吧,你可以在属性中使用consts,因为它们作为编译时存在。 您无法预测静态只读变量的值,因为.cctor可以从配置等初始化它。

在使用方面,常量被烧入调用代码中。 这意味着如果重新编译 dll来更改公共常量,但不更改消费者,那么消费者仍然会使用原始值。 使用只读变量,这不会发生。 翻转的是常量(非常,非常轻微)更快,因为它只是加载值(而不是必须取消引用它)。

重新实习; 虽然您可以手动执行此操作,但这通常是文字的编译器/运行时function; 如果你通过文字初始化一个只读字段:

 someField = "abc"; 

然后"abc"将被实习。 如果你从配置中读取它,它将不会。 因为常量字符串必须是文字,它也将被实现,但它的访问方式不同:再次,从字段读取是de-reference,而不是ldstr

实际上,这两种类型在初始化后无法更改,但它们之间存在一些差异:

  • ‘const’必须在声明它们的地方初始化(在编译时),而’readonly’可以在声明它的地方或构造函数(ar运行时)内初始化。

例如,const可以在这种情况下使用:

 public class MathValues { public const double PI = 3.14159; } 

对于这种情况,readonly会更好:

 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 constreadonlystatic readonly字段之间的区别(来自本文 )。

常数

  • 静态默认
  • 必须具有编译时间值(即:您可以拥有“A”+“B”但不能进行方法调用)
  • 可以在属性中使用
  • 被复制到使用它们的每个程序集中(每个程序集都获取值的本地副本)
  • 可以在函数内声明

只读实例字段

  • 在创建实例时进行评估
  • 必须在构造函数退出时设置值

静态只读字段

  • 在代码执行命中类引用时进行评估(即:创建新实例或执行静态方法)
  • 必须在静态构造函数完成时评估值
  • 你真的不想把ThreadStaticAttribute放在这些上(因为静态构造函数只会在一个线程中执行,它会为它的线程设置值;所有其他线程都会有这个值未初始化)

正在使用? 并不是的。 在编译时评估Consts,而在运行时评估readonly。 您还可以在构造函数中为readonly变量赋值。

C#.Net中的constreadonly字段之间存在显着差异

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是不可能的。

还有一件事。 我在上面的评论中没有看到这一点,虽然我可能错过了它。 您无法创建常量数组。

 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 }; 

不能用常数来做,可以吗?

可以在声明或类的构造函数中初始化只读字段。 因此,readonly字段可以具有不同的值,具体取决于所使用的构造函数

readonly成员也可用于运行时常量,如以下示例所示:

 public static readonly uint currentTicks = (uint)DateTime.Now.Ticks; 

只读字段不是隐式静态的,因此如果需要, 静态关键字可以(必须)显式应用于只读字段。 const字段不允许这样做,它们是隐式静态的。

Readonly成员可以在初始化时使用new关键字来保存复杂对象。

不同之处在于静态只读字段的值在运行时设置,因此可以由包含类修改,而const字段的值设置为编译时常量。

在静态只读的情况下,允许包含类仅修改它

在静态构造函数中的变量声明(通过变量初始化程序)(实例构造函数,如果它不是静态的),如果在const声明中不允许使用字段的类型,或者在未知的值时,通常使用静态只读编译时间。

实例只读字段也是允许的。

请记住,对于引用类型,在两种情况下(静态和实例),只读修饰符仅阻止您为字段分配新引用。 它特别不会使引用所指向的对象成为不可变的。

 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关键字来保存复杂对象。