C#中constreadonly什么区别?

您什么时候可以使用另一个?


#1楼

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

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

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

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

const

  • 不能将它们声明为static (它们是隐式静态的)
  • 在编译时评估常量的值
  • 常量仅在声明时初始化

只读

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

#2楼

常量将作为文字值编译到使用者中,而静态字符串将用作对所定义值的引用。

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


#3楼

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


#4楼

还有一个陷阱:只读值可以通过反射的“欺骗”代码来更改。

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

我可以使用反射更改C#中的私有只读继承字段吗?


#5楼

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

  • 当您拥有一个可以在运行时知道的类型的变量(字符串文字,int,double,enums ...)时,请使用const ,您希望类的所有实例或使用者都可以访问该值不应更改的位置。
  • 当您拥有希望类的所有实例或使用者可以访问值可以更改的位置的数据时,请使用static
  • 当您拥有一个在运行时(对象)不知道的类型的变量,而您希望某个类的所有实例或使用者都可以访问该值不应更改的位置时,请使用静态只读
  • 当您有一个实例级别的变量,该变量在创建对象时会知道,该变量不应更改,请使用readonly

最后一点:const字段是静态的,但反之则不正确。


#6楼

常量和只读类似,但是它们并不完全相同。 const字段是编译时常量,表示可以在编译时计算该值。 只读字段可启用其他方案,在该方案中,必须在类型构造期间运行某些代码。 构造后,只读字段无法更改。

例如,const成员可用于定义成员,例如:

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

因为像3.14和0这样的值是编译时常量。 但是,请考虑定义一种类型并想提供一些预制实例的情况。 例如,您可能想要定义一个Color类,并为常见的颜色(如黑色,白色等)提供“常量”。使用const成员是不可能的,因为右侧不是编译时常量。 可以使用常规静态成员执行此操作:

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的客户使用它了,也许可以通过交换Black和White值来避免。 不用说,这会使Color类的其他客户端感到震惊。 “只读”功能解决了这种情况。 通过在声明中简单地引入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成员始终是静态的,而readonly成员可以是静态的,也可以不是静态的,就像常规字段一样。

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

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

另一位开发人员编写了依赖于A的代码:

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

现在,生成的代码是否可以依赖AC是编译时常量的事实? 即,AC的使用是否可以简单地替换为值0? 如果对此说“是”,则意味着A的开发人员无法更改AC初始化的方式-未经许可,这会束缚A的开发人员的双手。 如果您对这个问题说“否”,那么将错过重要的优化。 也许A的作者肯定AC将始终为零。 const和readonly的使用允许A的开发人员指定意图。 这样可以实现更好的版本控制行为以及更好的性能。


#7楼

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


#8楼

有一个只读的小陷阱。 可以在构造函数中多次设置只读字段。 即使在两个不同的链式构造函数中设置了值,也仍然允许。


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

#9楼

不同之处在于,静态只读字段的值是在运行时设置的,因此对于程序的不同执行,它可以具有不同的值。 但是,const字段的值设置为编译时间常数。

切记:对于引用类型,在两种情况下(静态和实例),readonly修饰符仅阻止您为该字段分配新引用。 具体来说,它不会使引用指向的对象不可变。

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


#10楼

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

const在默认情况下是静态的,需要使用常量值进行初始化,以后将无法对其进行修改。 构造函数中也不允许更改值。 并非所有数据类型都可以使用它。 对于exDateTime。 不能与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可以声明为静态,但不是必需的。 声明时无需初始化。 可以使用构造函数来分配或更改其值。 因此,当用作实例类成员时,它具有优势。 两种不同的实例可能具有不同的只读字段值。 对于前-

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


#11楼

常量变量在编译时声明和初始化。 病房之后不能更改该值。 只读变量将仅从类的静态构造函数初始化。 只读仅在我们要在运行时分配值时使用。


#12楼

不变

定义时,我们需要将值提供给const字段。 然后,编译器将常量的值保存在程序集的元数据中。 这意味着只能为原始类型(如boolean,char,byte等)定义一个常量。 常量始终被视为静态成员,而不是实例成员。

只读

只读字段只能在运行时解析。 这意味着我们可以使用声明字段类型的构造函数为值定义一个值。 验证是由编译器完成的,除了构造方法外,只读字段没有被其他方法写入。

本文在此处详细介绍了两者


#13楼

常数

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

只读实例字段

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

静态只读字段

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

#14楼

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

常量 :通过消除静态。 不能在任何地方(Ctor,Function,运行时等,无处)更改值


#15楼

这是另一个链接,说明const如何不是版本安全的,或者与引用类型无关。

总结

  • const属性的值是在编译时设置的,在运行时不能更改
  • 常量不能被标记为静态-关键字表示它们是静态的,与只读字段不同。
  • 常量除值(原始)类型外不能为其他任何东西
  • readonly关键字将字段标记为不可更改。 但是,可以在类的构造函数中更改属性
  • readonly only关键字也可以与static组合使用,以使其与const(至少在表面上)具有相同的作用。 当您查看两者之间的IL时,有明显的区别
  • const字段在IL中被标记为“文字”,而readonly是“ initonly”

#16楼

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


#17楼

CONST

  1. const关键字可以应用于字段或局部变量
  2. 我们必须在声明时分配const字段
  3. 未分配内存,因为编译后const值已嵌入IL代码本身中。 就像找到所有出现的const变量并用其值替换一样。 因此,编译后的IL代码将具有硬编码的值来代替const变量
  4. C#中的常量默认情况下是静态的。
  5. 该值对于所有对象都是恒定的
  6. 存在dll版本控制问题-这意味着,每当我们更改公共const变量或属性时,(实际上,理论上就不应更改它),必须重新构建使用此变量的任何其他dll或程序集。
  7. 只能将C#内置类型声明为常量
  8. 常量字段不能作为ref或out参数传递

只读

  1. readonly关键字仅适用于字段,而不适用于局部变量
  2. 我们可以在声明时或在构造函数中分配只读字段,而不能在任何其他方法中分配。
  3. 为只读字段分配的动态内存,我们可以在运行时获取该值。
  4. 只读属于创建的对象,因此只能通过类的实例进行访问。 为了使其成为类成员,我们需要在只读之前添加static关键字。
  5. 该值可能会有所不同,具体取决于所使用的构造函数(因为它属于类的对象)
  6. 如果将非原始类型(引用类型)声明为只读,则仅引用是不可变的,而不是其中包含的对象。
  7. 由于该值是在运行时获取的,因此只读字段/属性没有dll版本控制问题。
  8. 我们可以在构造函数上下文中将readonly字段作为ref或out参数传递。

#18楼

常量 :应用程序生命周期内的绝对常数。

只读 :可以在运行时更改。


#19楼

我相信所有对象的const值都是相同的(必须使用文字表达式进行初始化),而每个实例的readonly可以不同。


#20楼

这说明了这一点 。 简介:const必须在声明时初始化,只读可以在构造函数上初始化(因此,根据所使用的构造函数的不同,其值也不同)。

编辑:请参阅上面的Gishu的陷阱以获得微妙的区别


#21楼

const是编译时常量,而readonly允许在运行时计算值并在构造函数或字段初始化程序中设置。 因此,“ const”始终是常数,但是“ readonly”在分配后是只读的。

C#小组的Eric Lippert拥有有关不同类型不变性的更多信息


#22楼

有一个const的陷阱! 如果从另一个程序集中引用一个常量,则其值将直接编译到调用程序集中。 这样,当您更新引用程序集中的常量时,在调用程序集中就不会更改它!


#23楼

除了明显的区别

  • 必须在定义const时声明值,VS readonly值可以动态计算,但需要在构造函数退出之前分配。在冻结之后。
  • 'const's是隐式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值的情况下,就像是一个查找替换,值2被“烘焙”到AssemblyB的IL中。 这意味着,如果明天我将在将来将I_CONST_VALUE更新为20。 在我重新编译之前, AssemblyB仍有2个
  • readonly值的情况下,就像对存储位置的ref 。 该值未烘焙到AssemblyB的IL中。 这意味着,如果内存位置已更新,则AssemblyB将获得新值,而无需重新编译。 因此,如果I_RO_VALUE更新为30,则只需要构建AssemblyA 。 不需要重新编译所有客户端。

因此,如果您确信常量的值不会改变,请使用const

public const int CM_IN_A_METER = 100;

但是,如果您有一个可能会更改的常量(例如,精度),或者有疑问,请使用readonly

public readonly float PI = 3.14;

更新:Aku需要得到提及,因为他首先指出了这一点。 此外,我需要插入那里,我知道这个.. 有效的C#比尔-瓦格纳


#24楼

标记为const的变量只不过是强类型的#define宏,在编译时,const变量引用将被内联文字值替换。 结果,只能以这种方式使用某些内置的原始值类型。 标记为只读的变量可以在构造函数中在运行时设置,并且它们的只读性也可以在运行时强制执行。 与此相关的性能开销很小,但这意味着您可以对任何类型(甚至是引用类型)使用只读。

同样,const变量本质上是静态的,而如果需要,只读变量可以是实例特定的。


#25楼

只需添加一下,对于引用类型的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 valueI_RO_VALUE = new char[]{'V'}; //will cause compiler error}
}

#26楼

  • 何时使用constreadonly

    • const

      • 编译时常量: 绝对常量,值在声明期间设置,在IL代码本身中
    • readonly

      • 运行时常量:可以通过配置文件(即App.config在构造函数/ init中设置,但一旦初始化,就无法更改

#27楼

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

readonly :只能在构造函数中更改此值。 在正常功能下无法更改。


#28楼

人们上面所说的补充一件事。 如果您有一个包含只读值的程序集(例如,readonly MaxFooCount = 4;),则可以通过发送具有不同值的该程序集的新版本来更改调用程序集所看到的值(例如,只读MaxFooCount = 5;)。

但是使用const时,将在编译调用方时将其折叠到调用方的代码中。

如果您已达到C#熟练程度,则可以阅读Bill Wagner的书《有效的C#:改善C#的50种特定方法》,该书将详细回答此问题(以及其他49项)。


#29楼

它们都是常量,但是在编译时也可以使用const。 这意味着区别的一方面是可以将const变量用作属性构造函数的输入,但不能使用readonly变量。

例:

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

#30楼

. 另一个 。

由于const实际上仅适用于基本数据类型,因此,如果要使用类,可能会感到“被迫”使用ReadOnly。 但是,请当心陷阱! ReadOnly表示您不能用另一个对象替换该对象(不能使其引用另一个对象)。 the object! 但是任何引用该对象的进程都可以自由修改该对象的值!

因此,不要误以为ReadOnly意味着用户无法更改任何东西。 C#中没有简单的语法可以防止类的实例更改其内部值(据我所知)。

C#中const和readonly有什么区别?相关推荐

  1. C#中const和readonly的区别

    C#引入了readonly修饰符来表示只读域,const来表示不变常量.顾名思义对只读域不能进行写操作,不变常量不能被修改,这两者到底有什么区别呢?只读域只能在初始化--声明初始化或构造器初始化--的 ...

  2. c#中const与readonly区别

    const表示常量,定义的时候就要初始化:readonly表示只读,定义的时候可以不初始化,可以延迟到构造方法中进行初始化. 以下转载的两篇文章写的很好. 转载 追梦赤子心 的文章:C#基础知识七之c ...

  3. C# 中const和readonly的区别

    const 的概念就是一个包含不能修改的值的变量. 常数表达式是在编译时可被完全计算的表达式.因此不能从一个变量中提取的值来初始化常量. 如果 const int a = b+1;b是一个变量,显然不 ...

  4. (转)c#中const与readonly区别

    const 的概念就是一个包含不能修改的值的变量. 常数表达式是在编译时可被完全计算的表达式.因此不能从一个变量中提取的值来初始化常量. 如果 const int a = b+1;b是一个变量,显然不 ...

  5. C++中const迭代器 和 const_iterator的区别

    话说这两个区别非常大,但是不太好理解啊,而且感觉解释也是各种绕口.说一下我自己的理解吧. const迭代器,顾名思义,就是不能改变的迭代器,是常量,其性质是由const决定的.比如说我们这样定义一个c ...

  6. const和readonly内部区别

    const和readonly关键字也是面试中经常考到的问题,通常都是用来表示一个不可变的变量成员,那么具体区别是什么?从用法上说,const只能以inline代码的形式定义,而readonly既可以以 ...

  7. php 中const define,PHP 中 const define 的区别

    在php中定义常量时,可用到const与define这两种方法,那他们到底有什么区别呢? 1.const用于类成员变量的定义,一经定义,不可修改.define不可用于类成员变量的定义,可用于全局常量. ...

  8. [c#] const 与 readonly

    c# 中 const 与 readonly 关键字看似相同,实则不同.重点在于确定值的时间. const const 很简单,就是一个常量,不可以被 static 修饰,因为被 const 修饰的字段 ...

  9. java post和put的区别,ES 中的 POST 和 PUT 的区别

    0.什么是Restful架构 比较难说清楚,这部分大雾状态,引ruanyf 理解RESTful架构 的几句总结吧: Fielding将他对互联网软件的架构原则,定名为REST,即Representat ...

最新文章

  1. 第十九章 9标签类Label
  2. VS2019编译 当前最新版chromium
  3. java 日期加一天_漫话:如何给女朋友解释为什么一到年底,部分网站就会出现日期混乱的现象?...
  4. 圆盘(抽奖)自定义View
  5. EasyMock 常见异常
  6. ckc交易什么意思_在期货交易中,所谓的期货对冲是什么意思?
  7. 【笔记】lamp架构框图
  8. ios查看ipa是否函数特定字符_利用strings 检测iOS ipa包是否调用私有api
  9. app端-留存分析-周留存率报表开发
  10. c语言怎么打尖括号,怎么在word中利用键盘快速输入尖括号
  11. 鸿蒙支持手机型号,推出鸿蒙,放弃安卓?华为新机入网,鸿蒙首发机型确定!...
  12. ppt中如何合并流程图_PPT中流程图如何分支?
  13. 爱 —— 哥林多前书(1 Corinthians)第13章
  14. [html+js][实现鼠标悬停事件]鼠标移动到行自动变色实现
  15. 企业信息安全很重要?私有化部署为企业信息保驾护航
  16. 数据中台到底如何落地实现【含架构图及代码】
  17. PAT A1153 Decode Registration Card of PAT ——凭谁问,廉颇老矣,尚能饭否
  18. 智能优化算法——免疫算法求解选址问题(PythonMatlab实现)
  19. 读书笔记:算法图解 using Python
  20. 用CSS/CSS3 实现 水平居中和垂直居中的完整攻略

热门文章

  1. erlang 常用函数
  2. flash as3鼠标左右拖动元件
  3. 如何稳定地使用 Google 搜索
  4. 【无线也安全】屏蔽蹭网一族
  5. INCEPTION 编译过程报错 make[2]: * [sql/CMakeFiles/sql.dir/sql_yacc.cc.o] Error
  6. 多个ajax执行混乱问题
  7. 什么样的人适合做自动化测试
  8. Java中的Swing键盘绑定案例
  9. BZOJ 3555 [CTSC2014] 企鹅QQ Hash
  10. 重复数据插入unique列时,锁加在哪?