在C#中常量和只读之间有什么区别?
你什么时候会用一个代替另一个?
在C#中常量和只读之间有什么区别?
你什么时候会用一个代替另一个?
当前回答
标记为const的变量只不过是强类型的#define宏,在编译时,const变量引用被替换为内联文本值。因此,只能以这种方式使用某些内置基元值类型。标记为只读的变量可以在运行时在构造函数中设置,并且它们的只读性也在运行时强制执行。与此相关的性能开销较小,但这意味着您可以对任何类型(甚至引用类型)使用只读。
此外,常量变量本质上是静态的,而只读变量如果需要可以是特定于实例的。
其他回答
我相信常量值对于所有对象都是相同的(并且必须用文字表达式初始化),而只读对于每个实例化可以是不同的。。。
C#.Net中常量字段和只读字段之间存在显著差异
const在默认情况下是静态的,需要用常量值初始化,以后不能修改。构造函数中也不允许更改值。它不能与所有数据类型一起使用。对于ex-DateTime。它不能与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
只读可以声明为静态,但不是必需的。无需在声明时进行初始化。它的值可以使用构造函数赋值或更改。因此,它在用作实例类成员时具有优势。两个不同的实例化可能具有不同的只读字段值。对于ex-
class A
{
public readonly int Id;
public A(int i)
{
Id = i;
}
}
然后,只读字段可以用即时特定值初始化,如下所示:
A objOne = new A(5);
A objTwo = new A(10);
这里,实例objOne的只读字段值为5,objTwo的值为10。这不可能使用常量。
有一件事要补充人们上面所说的。如果程序集包含只读值(例如,只读MaxFooCount=4;),则可以通过使用不同的值(例如只读MaxFooCount=5;)发送该程序集的新版本来更改调用程序集看到的值
但如果使用常量,则在编译调用者时,它将被折叠到调用者的代码中。
如果你已经达到了C#的熟练程度,你就可以阅读比尔·瓦格纳的书《有效的C#:提高你的C语言的50种具体方法》了#它详细回答了这个问题(以及其他49个问题)。
Const和readonly相似,但并不完全相同。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成员总是静态的,而只读成员可以是静态的,也可以不是静态的,就像常规字段一样。
可以将一个关键字用于这两个目的,但这会导致版本控制问题或性能问题。假设我们对这个(const)使用了一个关键字,一个开发人员写道:
public class A
{
public static const C = 0;
}
而另一位开发人员编写的代码依赖于a:
public class B
{
static void Main() {
Console.WriteLine(A.C);
}
}
现在,生成的代码是否可以依赖于A.C是一个编译时间常数这一事实?也就是说,A.C的使用是否可以简单地用值0代替?如果你对此说“是”,那么这意味着A的开发者不能改变A.C的初始化方式——这在未经许可的情况下束缚了A的开发者的双手。如果你对这个问题说“不”,那么就会错过一个重要的优化。也许A的作者肯定A的C值永远为零。const和readonly的使用允许A的开发人员指定意图。这有助于更好的版本控制行为和更好的性能。
它们都是常量,但在编译时也可以使用常量。这意味着差异的一个方面是,可以使用常量变量作为属性构造函数的输入,但不能使用只读变量。
例子:
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; }
}
}