const
变量和私有的static readonly
变量之间存在差异(除了必须为const
分配编译时表达式之外)?由于它们都是私有的,所以不会与其他库链接。 那么它会有任何区别吗? 例如,它能否产生性能差异? 集合字符串? 任何类似的东西?
你可以在属性中使用常量,因为它们存在于编译时。你无法预测静态只读变量的值,因为.cctor可能从配置等方面进行初始化。
就使用而言,常量被烧入调用代码中。这意味着如果重新编译一个公共常量所在的库 DLL,但不更改使用者,则使用者仍将使用原始值。对于只读变量,这种情况不会发生。相反,常量(非常,非常轻微地)更快,因为它仅加载值(而不必解引用)。
关于内部化;虽然您可以手动执行此操作,但这通常是文字字面量的编译器/运行时特性;如果通过文本字面量初始化只读字段:
someField = "abc";
那么"abc"
将被interned。如果你从配置文件中读取它,它将不会被interned。因为常量字符串必须是文字,所以它也会被interned,但它的访问方式不同:再次,从字段中读取是一个解引用,而不是ldstr
。
事实上,在初始化后,这两种类型都不能更改,但它们之间存在一些差异:
例如,const可在以下情况下使用:
public class MathValues
{
public const double PI = 3.14159;
}
只读对于这种情况更好:
public class Person
{
public readonly DateTime birthDate;
public Person(DateTime birthDate)
{
this.birthDate = birthDate;
}
}
或者public class Person
{
public readonly DateTime birthDate = new DateTime(1986, 1, 24);
}
'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 关键字),但不能保存枚举。
在C#.Net中,const和readonly字段之间有显著的区别。
const默认为静态,并且需要用常量值进行初始化,以后不能修改该值。构造函数中也不允许更改值。它不能与所有数据类型一起使用,例如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
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的只读字段值为5,而objTwo的值为10。这是使用const不可能实现的。
关于常量需要注意的一点是它们实际上存储在您的可执行文件中,因此声明了许多常量会增加您的可执行文件大小。
通常情况下,这不是一个很大的问题,但我的一个朋友曾在一家公司工作,该公司实行“一切都必须是常量”的规定,并成功地显著增加了他们编译后的可执行文件大小。
使用中?并不完全是这样。常量在编译时计算,而只读变量在运行时计算。您也可以在构造函数中为只读变量分配值。
static readonly字段的区别在于其值是在运行时设置的,因此可以被包含它的类修改,而const字段的值则被设置为编译时常量。
在静态只读情况下,包含它的类只允许在以下情况下进行修改:
在变量声明中(通过变量初始化器) 在静态构造函数中(如果不是静态,则在实例构造函数中) 通常情况下,如果字段的类型不允许在const声明中使用,或者当值在编译时未知时,会使用static readonly。
实例只读字段也是允许的。
请记住,对于引用类型,在静态和实例两种情况下,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;
}
C# .NET 中的 Const 关键字
示例:public const string abc = “xyz”;
只能在声明时初始化。
值在编译时计算,运行时不能更改。
试图更改它将导致编译错误。
Const 已经是一种静态类型。
由于类和结构体使用 new 关键字在运行时初始化,因此无法将常量设置为类或结构体。但是,它必须是整数类型之一。
C# .NET 中的 Readonly 关键字
示例:public readonly string abc;
可以在声明代码或构造函数代码中初始化。
值在运行时计算。
可以声明为静态或实例级别属性。
只读字段可以通过在运行时使用 new 关键字来保存复杂对象。
还有一件事。虽然我可能错过了,但我在上面的评论中没有看到这一点。您无法创建常量数组。
private const int[] values = new int[] { 1, 2, 3 };
但是你可以使用静态只读字段来创建它。
private static readonly int[] values = new int[] { 1, 2, 3 };
如果您需要一个数组常量,比如一组可允许的值,并且枚举不合适的话,那么静态只读是唯一的选择。例如,如果数组是可空整数数组,如下所示:
private static readonly int?[] values = new int?[] { null, 1, 2, 3 };
常量不支持这样的操作,对吧?
values
不能被设置为另一个数组,但是可以操作数组的元素:values[0] = 99
或者Array.Sort(values)
都会改变数组的值,即使它被声明为只读。虽然有一个ImmutableArray
类型,但这个话题超出了const和readonly关键字的基本实用性,并且偏离了问题的重点。 - C Perkins只读字段可以在类的声明或构造函数中进行初始化。因此,只读字段可以根据使用的构造函数而具有不同的值。
只读成员也可以用于运行时常量,如下例所示:
public static readonly uint currentTicks = (uint)DateTime.Now.Ticks;
只读字段并不是隐式静态的,因此如果需要,可以(必须)显式地将 static 关键字 应用于只读字段。但对于常量字段,则不允许这样做,因为它们是隐式静态的。
只读成员可以通过在初始化时使用 new 关键字 来持有复杂对象。