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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/410723/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 02:19:12  来源:igfitidea点击:

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

c#constreadonly

提问by Hosam Aly

Is there a difference between having a private constvariable or a private static readonlyvariable in C# (other than having to assign the consta 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?

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

采纳答案by Marc Gravell

Well, you can use consts in attributes, since they exist as compile time. You can't predict the value of a static readonly variable, since the .cctorcould initialize it from configuration etc.

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

In terms of usage, constants are burnt into the calling code. This means that if you recompile a librarydll to change a publicconstant, but don't change the consumers, then he consumers will still use the original value. 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).

在使用方面,常量被烧录到调用代码中。这意味着如果您重新编译dll 以更改公共常量,但不更改消费者,那么他的消费者仍将使用原始值。使用只读变量不会发生这种情况。与此相反的是,常量(非常非常轻微)更快,因为它只是加载值(而不是取消引用它)。

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. 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.

然后"abc"将被实习。如果您从配置中读取它,则不会。因为常量字符串必须是文字,所以它也将被内嵌,但它的访问方式不同:同样,从字段中读取是取消引用,而不是ldstr.

回答by Steven Robbins

In use? Not really. Consts are evaluated at compile time, whereas readonly are evaluated at runtime. You can also assign a readonly variable a value in the constructor.

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

回答by Soviut

Something to note about constants is they're actually stored in your executable, so declaring a lot of them willincrease 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.

通常,这不是一个大问题,但我的一个朋友在公司工作,该公司强制执行“一切都必须是常量”规则并设法显着增加其编译后的可执行文件大小。

回答by melculetz

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:

对于这种情况,只读会更好:

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. As a consequence a declaration like 'static const' is illegal because const is static, but 'static readonly' is legal

  • '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' 是静态的,因此它在该类的所有实例之间共享并且可以直接访问(如 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 关键字)但不能保存枚举

回答by splattne

Readonly fields can be initialized either at the declarationor in a constructorof a class. Therefore readonly fields can have different values depending on the constructor used.

只读字段可以在类的声明构造函数中初始化。因此,只读字段可以根据使用的构造函数具有不同的值

A readonly member can also be used for runtime constantsas in the following example:

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

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

Readonly fields are notimplicitly static, and therefore the static keywordcan (must) be applied to a readonly field explicitly if required. This is not allowed for const fields, which are implicitly static.

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

Readonly members can hold complex objects by using the new keyword at initialization.

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

回答by Rinat Abdullin

Here are the differences between C# .NET const, readonlyand static readonlyfields (from this article).

以下是 C# .NET constreadonlystatic readonly字段之间的区别(来自本文)。

Constants:

常数

  • Static by default
  • Must have compilation-time value (i.e.: you can have "A"+"B" but cannot have method calls)
  • 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
  • 默认静态
  • 必须有编译时值(即:你可以有“A”+“B”但不能有方法调用)
  • 可以在属性中使用
  • 被复制到使用它们的每个程序集中(每个程序集都获得值的本地副本)
  • 可以在函数内声明

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 (i.e.: 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 放在这些上(因为静态构造函数只会在一个线程中执行,它会为它的线程设置值;所有其他线程都没有初始化这个值)

回答by Rinat Abdullin

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 声明中不允许该字段的类型,或者当值未知时,通常使用 static readonly编译时间。

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.

请记住,对于引用类型,在两种情况下(静态和实例), 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;

}


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. To expand on the static read-only case a bit, the containing class can only modify it:

不同之处在于静态只读可以被包含类修改,而 const 永远不能修改,必须初始化为编译时常量。为了稍微扩展静态只读情况,包含类只能修改它:

-- 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”;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. Since classes and structs are initialized at run time with new keyword, you can't set a constant to a class or structure. But, it has to be one of the integral types. Readonly Keyword in C# .NET

示例:public const string abc = “xyz”;仅在声明时初始化。值在编译时评估,不能在运行时更改。尝试更改它会导致编译错误。Const 已经是静态的了。由于类和结构是在运行时使用 new 关键字初始化的,因此您不能为类或结构设置常量。但是,它必须是整数类型之一。C# .NET 中的只读关键字

Example: public readonly string abc;Can be initialized in declaration code or consturctor code. 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.

示例:public readonly string abc;可以在声明代码或构造函数代码中初始化。在运行时评估值。可以声明为静态或实例级属性。通过在运行时使用 new 关键字,只读字段可以保存复杂对象。

回答by Mel

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 cancreate 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:

因此,如果您需要一个数组常量,例如一个允许值列表,而枚举不合适,那么静态 readonly 是唯一的方法。例如,如果数组是可为空的整数,如下所示:

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

Can't do thatwith a constant, can ya?

不能用常数来做到这一点,是吗?

回答by Chirag

There is notable difference between constand readonlyfields 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. 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.

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 can be declared as static, but not necessary. 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 -

readonly 可以声明为静态,但不是必需的。无需在声明时初始化。可以使用构造函数分配或更改其值。因此,当用作实例类成员时,它具有优势。两个不同的实例化可能具有不同的 readonly 字段值。对于前 -

class A
{
    public readonly int Id;

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

Then readonly field can be initialised with instant specific values, as follows:

然后可以使用即时特定值初始化只读字段,如下所示:

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