const和readonly有什么区别?

constreadonly什么区别,你用另一个呢?

除了明显的区别之外

  • 不得不声明const的定义时的值VS readonly值可以dynamic计算,但需要在构造函数退出之前分配。在此之后它被冻结。
  • const的隐含的是static 。 您使用ClassName.ConstantName表示法来访问它们。

有一个微妙的区别。 考虑在AssemblyA定义的一个类。

 public class Const_V_Readonly { public const int I_CONST_VALUE = 2; public readonly int I_RO_VALUE; public Const_V_Readonly() { I_RO_VALUE = 3; } } 

AssemblyB引用AssemblyA并在代码中使用这些值。 当这个被编译时,

  • const值的情况下,它就像一个查找replace,值2被“烘焙”到AssemblyB的IL中。 这意味着如果明天我将来将I_CONST_VALUE更新为20。 AssemblyB将仍然有2,直到我重新编译它
  • readonly值的情况下,它就像是一个内存位置的ref 。 这个价值不是汇入AssemblyB的IL。 这意味着,如果内存位置更新, AssemblyB将获得新的值,而无需重新编译。 所以如果I_RO_VALUE更新到30,你只需要build立AssemblyA 。 所有客户端不需要重新编译。

所以如果你确信这个常量的值不会改变,就使用一个const

 public const int CM_IN_A_METER = 100; 

但是,如果你有一个常数,可能会改变(egwrt精度)..或有疑问时,使用readonly

 public readonly float PI = 3.14; 

更新:阿库需要提一下,因为他首先指出了这一点。 另外我需要插入的地方,我了解到这一点.. 有效的C# – 比尔瓦格纳

有一个常见问题! 如果您从另一个程序集引用常量,则其值将被编译到调用程序集中。 这样,当你更新引用程序集中的常量时,它不会在调用程序集中更改!

常量

  • 常量默认是静态的
  • 它们在编译时必须有一个值(你可以有例如3.14 * 2,但是不能调用方法)
  • 可以在函数内声明
  • 被复制到每个使用它们的程序集中(每个程序集都获得一个值的本地副本)
  • 可以在属性中使用

只读实例字段

  • 必须具有设定值,在构造函数退出时
  • 在创build实例时进行评估

静态只读字段

  • 在代码执行到达类引用时进行评估(当创build新实例或执行静态方法时)
  • 在静态构造函数完成时,必须有一个评估值
  • 不build议将ThreadStaticAttribute放在这些上(静态构造函数将只在一个线程中执行,并将为其线程设置值;所有其他线程都将此值初始化)

只是添加,ReadOnly参考types只使参考readonly不是值。 例如:

 public class Const_V_Readonly { public const int I_CONST_VALUE = 2; public readonly char[] I_RO_VALUE = new Char[]{'a', 'b', 'c'}; public UpdateReadonly() { I_RO_VALUE[0] = 'V'; //perfectly legal and will update the value I_RO_VALUE = new char[]{'V'}; //will cause compiler error } } 

这解释了它 。 总结:const必须在声明时初始化,只能在构造函数上初始化(因而根据所使用的构造函数有不同的值)。

编辑:见Gishu上面的细微差别

const :不能在任何地方改变。

readonly :只能在构造函数中更改此值。 在正常function下不能更改。

只读有一个小问题。 只读字段可以在构造函数中多次设置。 即使该值设置在两个不同的链式构造函数中,它仍然是允许的。

 public class Sample { private readonly string ro; public Sample() { ro = "set"; } public Sample(string value) : this() { ro = value; // this works even though it was set in the no-arg ctor } } 

const是一个编译时常量,而readonly允许在运行时计算一个值,并在构造函数或字段初始值设定器中进行设置。 所以,一个“const”总是不变的,但是“只读”一旦被赋值就是只读的。

C#团队的Eric Lippert拥有更多有关不变types不变性的信息

下面是另一个链接,演示const如何不是版本安全的,或者与引用types相关。

总结

  • const属性的值是在编译时设置的,不能在运行时改变
  • 常量不能被标记为静态 – 关键字表示它们是静态的,不像只读域可以。
  • 除了值(原始)types,Const不能是任何东西
  • readonly关键字将该字段标记为不可更改。 然而,该属性可以在类的构造函数内部进行更改
  • readonly only关键字也可以与static结合起来,使其与const(至less在表面上)的行为相同。 当你看两者之间的IL时,有一个显着的差异
  • IL中的const字段被标记为“literal”,而readonly是“initonly”

常量成员在编译时定义,不能在运行时更改。 常量使用const关键字声明为一个字段,并且必须在声明它们时进行初始化。

 public class MyClass { public const double PI1 = 3.14159; } 

readonly成员就像一个常数,它代表着一个不变的价值。 区别在于readonly成员可以在运行时初始化,在构造函数中初始化,并且可以在声明时进行初始化。

 public class MyClass1 { public readonly double PI2 = 3.14159; //or public readonly double PI3; public MyClass2() { PI3 = 3.14159; } } 

常量

  • 它们不能被声明为static (它们是隐含的静态的)
  • 常量的值在编译时进行评估
  • 常量只在声明时初始化

只读

  • 它们可以是实例级别的也可以是静态的
  • 该值在运行时进行评估
  • readonly可以在声明中或通过构造函数中的代码进行初始化

还有一个问题:只读值可以通过reflection来改变“迂回”的代码。

 var fi = this.GetType() .BaseType .GetField("_someField", BindingFlags.Instance | BindingFlags.NonPublic); fi.SetValue(this, 1); 

我可以使用reflection在C#中更改私有只读inheritance的字段吗?

我相信一个const值对所有对象都是一样的(并且必须用一个文字expression式来初始化),而readonly对于每个实例都是不同的。

标记为const的variables比强types的#definemacros多一点,在编译时constvariables引用被replace为内联文字值。 因此,只有某些内置的原始值types可以以这种方式使用。 标记为readonly的variables可以在运行时在构造函数中设置,在运行时也可以强制执行read-only。 有一些小的性能成本与此相关,但它意味着您可以使用任何types(甚至参考types)只读。

此外,constvariables本质上是静态的,而只读variables可以是实例特定的,如果需要的话。

readonly关键字与const关键字不同。 const字段只能在该字段的声明处初始化。 readonly字段可以在声明中或在构造函数中初始化。 因此,只读字段可以具有不同的值,具体取决于所使用的构造函数。 另外,虽然const字段是编译时常量,但只读字段可用于运行时常量,如以下示例中所示:

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

另一个问题

由于const实际上只适用于基本的数据types,所以如果你想使用一个类,你可能会“强迫”使用ReadOnly。 不过,小心这个陷阱! ReadOnly表示不能用另一个对象replace对象(不能将其引用到另一个对象)。 但是任何具有对象引用的进程都可以自由修改对象内部的值!

所以不要混淆成只读意味着用户不能改变的东西。 在C#中没有简单的语法来防止类的实例化,其内部值发生了变化(据我所知)。

我们办公室的一个团队成员就何时使用const,static和readon提供了以下指导:

  • 当你有一个你可以在运行时知道的types的variables(string文字,int,double,enums,…)的时候使用const ,你希望一个类的所有实例或者使用者有权访问值不应该改变的地方。
  • 当有数据时,请使用静态 ,以便让所有实例或类的使用者有权访问值可以更改的位置。
  • 当你有一个你不能在运行时知道的types的variables(对象)时,使用静态只读方法 ,你希望所有的类的实例或消费者有权访问值不应该改变的地方。
  • 当你有一个实例级别的variables时使用readonly ,你将会在创build对象时知道这个variables不应该改变。

最后一个注意:const字段是静态的,但是反过来是不正确的。

它们都是不变的,但是在编译时也可以使用const。 这意味着差异的一个方面就是你可以使用constvariables作为input来赋值构造函数,而不是只读variables。

例:

 public static class Text { public const string ConstDescription = "This can be used."; public readonly static string ReadonlyDescription = "Cannot be used."; } public class Foo { [Description(Text.ConstDescription)] public int BarThatBuilds { { get; set; } } [Description(Text.ReadOnlyDescription)] public int BarThatDoesNotBuild { { get; set; } } } 

只读 :可以在运行时通过Ctor更改值。 但不是通过成员函数

常数 :通过defult static。 值不能从任何地方改变(Ctor,Function,运行时间等)

C#.Net中的const和只读字段有明显的区别

const默认是静态的,需要用常量初始化,以后不能修改。 构造函数中也不允许改变值。 它不能与所有的数据types一起使用。 对于以前的DateTime。 它不能与DateTime数据types一起使用。

 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 

只读可以声明为静态,但不是必需的。 申报时无需进行初始化。 它的值可以使用构造函数分配或更改。 所以,当它被用作实例类成员时,它就有了优势。 只有两个不同的实例可能具有不同的只读字段值。 对于前 –

 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。

不变

定义时,我们需要为const字段提供值。 编译器然后将常量的值保存在程序集的元数据中。 这意味着一个常量只能被定义为像布尔型,字符型,字节型等基本types。 常量被认为是静态成员,而不是实例成员。

只读

只读字段只能在运行时parsing。 这意味着我们可以使用构造函数为声明字段的types定义值的值。 validation是由编译器完成的,只读字段不是通过构造函数以外的任何方法写入的。

更多关于这两个在这里解释这篇文章

readonly关键字与const关键字不同。 const字段只能在该字段的声明处初始化。 readonly字段可以在声明中或在构造函数中初始化。 因此, 只读字段可以具有不同的值,具体取决于所使用的构造函数。 另外,虽然const字段是编译时常量,但只读字段可用于运行时常量,如以下示例中所示:

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

原则上; 您可以在运行时将静态只读字段的值赋予非常量值,而const则必须赋予常量值。

一个常量将作为一个字面值被编译到消费者中,而静态string将作为定义值的引用。

作为练习,尝试创build一个外部库并在控制台应用程序中使用它,然后更改库中的值并重新编译它(不需要重新编译使用者程序),将DLL放到目录中并手动运行EXE,应该会发现该常量string不会改变。

一个const必须是硬编码的 ,其中readonly可以在类的构造函数设置

Const和readonly是相似的,但它们并不完全一样。 const字段是一个编译时常量,意味着这个值可以在编译时计算出来。 只读字段使得在构buildtypes期间必须运行一些代码的附加场景成为可能。 施工结束后,只能读取字段不能更改。

例如,const成员可以用来定义成员,如:

 struct Test { public const double Pi = 3.14; public const int Zero = 0; } 

因为像3.14和0这样的值是编译时常量。 但是,请考虑您定义types并希望提供一些预制实例的情况。 例如,你可能想要定义一个Color类,并为黑色,白色等常见的颜色提供“常量”。这是不可能的,因为右边不是编译时常量。 可以用普通的静态成员来做到这一点:

 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 = r; green = g; blue = b; } } 

但是没有任何东西可以让Color的一个客户免受黑客的攻击,也许通过交换黑白价值。 不用说,这会导致Color类的其他客户感到惊愕。 “只读”function解决了这种情况。 通过简单地在声明中引入readonly关键字,我们保持了灵活的初始化,同时防止客户端代码被混淆。

 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 = r; green = g; blue = b; } } 

有趣的是,const成员总是静态的,而只读成员可以是静态的,也可以不是静态的,就像普通的成员一样。

为了这两个目的,可以使用单个关键字,但这会导致版本问题或性能问题。 假设我们使用了一个关键字(const),一个开发者写道:

 public class A { public static const C = 0; } 

而不同的开发者写的代码依赖于A:

 public class B { static void Main() { Console.WriteLine(AC); } } 

现在,生成的代码是否可以依赖于AC是编译时常量? 也就是说,交stream电的使用可以简单地用0代替吗? 如果你对此表示“是”,那么这意味着A的开发者不能改变AC被初始化的方式 – 这在未经许可的情况下将A的开发者的手联系起来。 如果你对这个问题说“不”,那么错过了一个重要的优化。 也许A的作者肯定AC会始终为零。 同时使用const和readonly允许A的开发人员指定意图。 这使得更好的版本行为和更好的性能。

ReadOnly:该值将从类的构造函数中初始化一次。
const:可以在任何函数中初始化,但只能进行一次

区别在于静态只读字段的值是在运行时设置的,所以对于程序的不同执行可以有不同的值。 但是,const字段的值被设置为编译时间常量。

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

有关详细信息,请参阅有关此主题的C#常见问题解答: http : //blogs.msdn.com/csharpfaq/archive/2004/12/03/274791.aspx

常量variables是在编译时声明和初始化的。 病房后不能改变这个值。 只读variables将仅从类的Static构造函数初始化。 只读只在我们想要在运行时分配值时使用。

const字段只能在该字段的声明处初始化。 readonly字段可以在声明中或在构造函数中初始化。

有一点要补充的是上面所说的人。 如果你有一个包含只读值的程序集(例如,只读MaxFooCount = 4;),你可以通过以不同的值传送该程序集的新版本来更改调用程序集所看到的值(例如,只读MaxFooCount = 5;)

但是对于一个const,当调用者被编译时,它将被折叠到调用者的代码中。

如果你已经达到了C#水平,那么你已经准备好了比尔·瓦格纳的书,有效的C#:50具体的方法来提高你的C#这个问题的答案详细(和其他49)。