简体   繁体   English

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

[英]Is there a difference between private const and private readonly variables in C#?

Is there a difference between having a private const variable or a private static readonly variable in C# (other than having to assign the const a compile-time expression)? 在C#中使用private const变量或private static readonly变量之间是否有区别(除了必须为const分配编译时表达式)?

Since they are both private, there is no linking with other libraries. 由于它们都是私有的,因此没有与其他库的链接。 So would it make any difference? 它会有什么不同吗? Can it make a performance difference for example? 例如,它可以产生性能差异吗? Interned strings? 实习字符串? Anything similar? 有什么相似的吗?

Well, you can use consts in attributes, since they exist as compile time. 好吧,你可以在属性中使用consts,因为它们作为编译时存在。 You can't predict the value of a static readonly variable, since the .cctor could initialize it from configuration etc. 您无法预测静态只读变量的值,因为.cctor可以从配置等初始化它。

In terms of usage, constants are burnt into the calling code. 在使用方面,常量被烧入调用代码中。 This means that if you recompile a library dll to change a public constant, but don't change the consumers, then he consumers will still use the original value. 这意味着如果重新编译 dll来更改公共常量,但不更改消费者,那么消费者仍将使用原始值。 With a readonly variable this won't happen. 使用只读变量,这不会发生。 The flip of this is that constants are (very, very slightly) quicker, since it simply loads the value (rather than having to de-reference it). 这样做的结果是常量(非常,非常轻微)更快,因为它只是加载值(而不是必须取消引用它)。

Re interning; 重新实习; although you can do this manually, this is most commonly a compiler/runtime feature of literals; 尽管您可以手动执行此操作,但这通常是文字的编译器/运行时功能; if you init a readonly field via a literal: 如果你通过文字初始化一个只读字段:

someField = "abc";

then the "abc" will be interned. 然后"abc"将被实习。 If you read it from config, it won't be. 如果你从配置中读取它,它将不会。 Because a constant string must be a literal, it will also be interned, but it is accessed differently: again, reading from the field is a de-reference, rather than a ldstr . 因为常量字符串必须是文字,所以它也会被实习,但它的访问方式不同:再次,从字段读取是一个去引用,而不是ldstr

Indeed, the two types cannot be changed after they were initialized, but there are some differences between them: 实际上,这两种类型在初始化后无法更改,但它们之间存在一些差异:

  • 'const' must be initialized where they are declared(at compile time), whereas 'readonly' can be initialized where it is declared or inside the constructor (ar runtime). 'const'必须在声明它们的地方初始化(在编译时),而'readonly'可以在声明它的地方或构造函数(ar运行时)内初始化。

For example const could be used in this situation: 例如,const可以在这种情况下使用:

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

And readonly would be better for this case: 对于这种情况,readonly会更好:

public class Person
{
    public readonly DateTime birthDate;

    public Person(DateTime birthDate)
    {
        this.birthDate = birthDate;
    }
}

or 要么

public class Person
{
    public readonly DateTime birthDate = new DateTime(1986, 1, 24);
}
  • 'const' is static, so it is shared between all instances of that class and can be accessed directly (like MathValues.PI), whereas 'readonly' is not static. 'const'是静态的,因此它在该类的所有实例之间共享,可以直接访问(如MathValues.PI),而'readonly'不是静态的。 As a consequence a declaration like 'static const' is illegal because const is static, but 'static readonly' is legal 因此,像'static const'这样的声明是非法的,因为const是静态的,但'static readonly'是合法的

  • 'const' can hold only integral type (sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool, or string), an enumeration, or a reference to null (not classes or structures because they are initialized at runtime, with the 'new' keyword), whereas 'readonly' can hold complex types, structures or classes (by using the new keyword at initialization) but cannot hold enumerations 'const'只能包含整数类型(sbyte,byte,short,ushort,int,uint,long,ulong,char,float,double,decimal,bool或string),枚举或对null的引用(不是类)或者结构因为它们是在运行时使用'new'关键字初始化的,而'readonly'可以包含复杂的类型,结构或类(通过在初始化时使用new关键字)但不能保存枚举

Something to note about constants is they're actually stored in your executable, so declaring a lot of them will increase your executable file size. 有关常量的注意事项是它们实际上存储在您的可执行文件中,因此声明其中很多增加您的可执行文件大小。

Normally, this isn't a huge problem, but a friend of mine worked at company that enforced an "everything must be const" rule and managed to significantly increase their compiled executable size. 通常,这不是一个大问题,但是我的一个朋友在公司工作,强制执行“一切必须是const”规则,并设法显着增加他们编译的可执行文件大小。

Here are the differences between C# .NET const , readonly and static readonly fields (from this article ). 以下是C#.NET constreadonlystatic readonly字段之间的区别(来自本文 )。

Constants : 常数

  • Static by default 静态默认
  • Must have compilation-time value (ie: you can have "A"+"B" but cannot have method calls) 必须具有编译时间值(即:您可以拥有“A”+“B”但不能进行方法调用)
  • Can be used in attributes 可以在属性中使用
  • Are copied into every assembly that uses them (every assembly gets a local copy of values) 被复制到使用它们的每个程序集中(每个程序集都获取值的本地副本)
  • Could be declared within functions 可以在函数内声明

Readonly instance fields : 只读实例字段

  • Are evaluated when instance is created 在创建实例时进行评估
  • Must have set value by the time constructor exits 必须在构造函数退出时设置值

Static readonly fields : 静态只读字段

  • Are evaluated when code execution hits class reference (ie: new instance is created or static method is executed) 在代码执行命中类引用时进行评估(即:创建新实例或执行静态方法)
  • Must have evaluated value by the time static constructor is done 必须在静态构造函数完成时评估值
  • You really do not want to put ThreadStaticAttribute on these (since static constructor will be executed in one thread only and it will set value for its thread; all other threads will have this value uninitialized) 你真的不想把ThreadStaticAttribute放在这些上(因为静态构造函数只会在一个线程中执行,它会为它的线程设置值;所有其他线程都会将此值保持为未初始化)

There is notable difference between const and readonly fields in C#.Net C#.Net中的constreadonly字段之间存在显着差异

const is by default static and needs to be initialized with constant value, which can not be modified later on. const默认为static,需要使用常量值进行初始化,以后不能修改。 Change of value is not allowed in constructors, too. 构造函数中也不允许更改值。 It can not be used with all datatypes. 它不能与所有数据类型一起使用。 For ex- DateTime. 对于前日期时间。 It can not be used with DateTime datatype. 它不能与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 can be declared as static, but not necessary. readonly可以声明为static,但不是必需的。 No need to initialize at the time of declaration. 无需在声明时初始化。 Its value can be assigned or changed using constructor. 可以使用构造函数指定或更改其值。 So, it gives advantage when used as instance class member. 因此,它在用作实例类成员时具有优势。 Two different instantiation may have different value of readonly field. 两个不同的实例化可能具有不同的只读字段值。 For ex - 对于前 -

class A
{
    public readonly int Id;

    public A(int i)
    {
        Id = i;
    }
}

Then readonly field can be initialised with instant specific values, as follows: 然后,readonly字段可以使用即时特定值进行初始化,如下所示:

A objOne = new A(5);
A objTwo = new A(10);

Here, instance objOne will have value of readonly field as 5 and objTwo has 10. Which is not possible using const. 这里,实例objOne的readonly字段值为5,objTwo的值为10.使用const不可能。

In use? 正在使用? Not really. 并不是的。 Consts are evaluated at compile time, whereas readonly are evaluated at runtime. 在编译时评估Consts,而在运行时评估readonly。 You can also assign a readonly variable a value in the constructor. 您还可以在构造函数中为readonly变量赋值。

One more thing. 还有一件事。 I didn't see this in the comments above, although I may have missed it. 我在上面的评论中没有看到这一点,虽然我可能错过了它。 You cannot create a constant array. 您无法创建常量数组。

private const int[] values = new int[] { 1, 2, 3 };

But you can create it using a static readonly field. 但您可以使用静态只读字段创建它。

private static readonly int[] values = new int[] { 1, 2, 3 };

So if you need an array constant, such as a list of allowable values, and an enumeration would not be appropriate, then the static readonly is the only way to go. 因此,如果您需要一个数组常量,例如允许值列表,并且枚举不合适,那么静态只读是唯一的方法。 For instance, if the array were of nullable integers, like this: 例如,如果数组是可空的整数,如下所示:

private static readonly int?[] values = new int?[] { null, 1, 2, 3 };

Can't do that with a constant, can ya? 不能做到这一点与恒定的,可以吧?

The difference is that the value of a static readonly field is set at run time, and can thus be modified by the containing class, whereas the value of a const field is set to a compile time constant. 不同之处在于静态只读字段的值在运行时设置,因此可以由包含类修改,而const字段的值设置为编译时常量。

In the static readonly case, the containing class is allowed to modify it only 在静态只读的情况下,允许包含类仅修改它

in the variable declaration (through a variable initializer) in the static constructor (instance constructors, if it's not static) static readonly is typically used if the type of the field is not allowed in a const declaration, or when the value is not known at compile time. 在静态构造函数(实例构造函数,如果它不是静态的)中的变量声明(通过变量初始化程序)中,如果在const声明中不允许使用字段的类型,或者在未知的值时,通常使用静态只读编译时间。

Instance readonly fields are also allowed. 实例只读字段也是允许的。

Remember that for reference types, in both cases (static and instance) the readonly modifier only prevents you from assigning a new reference to the field. 请记住,对于引用类型,在两种情况下(静态和实例),只读修饰符仅阻止您为字段分配新引用。 It specifically does not make immutable the object pointed to by the reference. 它具体不会使引用所指向的对象成为不可变的。

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;

}

The difference is that static read-only can be modified by the containing class, but const can never be modified and must be initialized to a compile time constant. 区别在于静态只读可以由包含类修改,但const永远不能被修改,必须初始化为编译时常量。 To expand on the static read-only case a bit, the containing class can only modify it: 要稍微扩展静态只读的情况,包含类只能修改它:

-- in the variable declaration (through a variable initializer). - 在变量声明中(通过变量初始化器)。

-- in the static constructor (instance constructors if it's not static). - 在静态构造函数中(实例构造函数,如果它不是静态的)。


Const Keyword in C# .NET C#.NET中的Const关键字

Example: public const string abc = “xyz”; 示例: public const string abc = “xyz”; Initialized only at declaration. 仅在声明时初始化。 Value is evaluated at compile time and can not be changed at run time. 值在编译时计算,不能在运行时更改。 An attempt to change it will cause a compilation error. 尝试更改它将导致编译错误。 Const is already kind of static. Const已经是一种静态的。 Since classes and structs are initialized at run time with new keyword, you can't set a constant to a class or structure. 由于类和结构在运行时使用new关键字初始化,因此无法为类或结构设置常量。 But, it has to be one of the integral types. 但是,它必须是不可或缺的类型之一。 Readonly Keyword in C# .NET C#.NET中的只读关键字

Example: public readonly string abc; 示例: public readonly string abc; Can be initialized in declaration code or consturctor code. 可以在声明代码或consturctor代码中初始化。 Value is evaluated at run time. 在运行时评估值。 Can be declared as static or instance level attribute. 可以声明为静态或实例级属性。 A read only field can hold a complex object by using the new keyword at run time. 只读字段可以在运行时使用new关键字来保存复杂对象。

Readonly fields can be initialized either at the declaration or in a constructor of a class. 可以在声明或类的构造函数中初始化只读字段。 Therefore readonly fields can have different values depending on the constructor used . 因此,readonly字段可以具有不同的值,具体取决于所使用的构造函数

A readonly member can also be used for runtime constants as in the following example: readonly成员也可用于运行时常量,如以下示例所示:

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

Readonly fields are not implicitly static, and therefore the static keyword can (must) be applied to a readonly field explicitly if required. 只读字段不是隐式静态的,因此如果需要, 静态关键字可以(必须)显式应用于只读字段。 This is not allowed for const fields, which are implicitly static. const字段不允许这样做,它们是隐式静态的。

Readonly members can hold complex objects by using the new keyword at initialization . Readonly成员可以在初始化时使用new关键字来保存复杂对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM