以下有什么区别吗?
class C
{
// One:
public static readonly int ValueAsAMember = 42;
// Two:
public static int ValueAsAProperty { get { return 42; } }
}
我习惯用第一种方式编写常量(除非它们是私有/内部的,在这种情况下我使用
const
关键字),但我最近看到了第二种形式。
在可读性、约定、性能或其他方面,一种方式比另一种方式有什么优势吗?
您有三个选择:
public static readonly int Value = 42;
public static int Value { get { return 42; } }
public const int Value = 42;
如果该值在运行时不会更改,但可能会在代码的未来版本中更改,请选择
static readonly
。
如果值可能在运行时更改,请选择一个属性。当然,如果您使用给定的代码,它不会改变。
如果该值确实是一个常数,在未来版本中甚至不会更改(例如
const
或 Math.PI
),请选择 int.MinValue
。当然,const
的使用受到值类型的限制。
const
和static readonly
之间的区别在于const
值将在调用站点被替换。如果您在未来版本中更改 const
的值,则所有依赖于您的类的程序集都需要使用新值重新编译。
属性需要方法调用(调用getter就是方法调用)。因此,如果该值在运行时是恒定的,则不需要这样做。
是的,有一个优点:
如果该值在未来的任何时候(例如在代码的未来版本中)可以更改,例如,以时间相关的方式更改,您可以在只读属性中支持该更改,而无需更改您班级的公共接口。
如果必须用属性替换
readonly
字段,则必须重新编译使用您的类的任何其他程序集。
有两个主要区别:
首先,字段不能位于接口上,而属性可以。所以如果你想在界面中使用它,你必须使用该属性。
第二个更有趣的是,在构造对象时可以修改
readonly
字段。采取以下代码:
public class MyTestClass
{
public readonly int MyInt = 1;
public MyTestClass()
{
MyInt = 2;
}
}
如果来电者这样做
new MyTestClass().MyInt
他们将得到 2。静态
readonly
字段的静态构造函数也是如此。
我认为,使用第一种方式更好地描述了值的意图 - 即它是不可变的。当一个人查看类的接口时,他会看到该值是只读的,并且不必怀疑以后是否可以更改(因为在第二种情况下,他看不到属性的实现) .
关于
const
声明需要注意的一个重要事项(我不认为对于 readonly
来说是这样),更改字段的值构成 API 更改,即使您只是将值从 42
更改为 41
。原因是,对于 consts
,该值是在编译时确定的,这意味着如果我编译一个使用您的常量的模块,并且您稍后更改它,我仍将使用旧值,直到我重新编译我的模块你的新版本。
我认为第一行使用 readonly 关键字使某些内容保持不变或只读。
第二行是利用属性来实现只读。两者的作用相同,但如果与 IL 进行比较,该属性会向 dll 添加几行额外的代码。
对我来说主要的优点是
readonly
你可以在代码中的任何地方声明它。但是,您将有机会仅设置它一次。使用 setter,您可以一键声明和设置。
属性只是字段周围的语法糖,没有设置器的属性只是声明为只读字段,因此编译器将允许您在构造函数中的运行时设置它,因为对于您正在引用的编译器一个 readonly 字段。关于如何使用字段或属性有一个更大的讨论,这不在问题的范围内。是的,你必须重新编译 @SOreadytohelp 引用的这个语法糖。需要明确的是,属性是一个为其创建了 get 和 set 方法的字段,C# 将允许您像字段一样引用它,而不是每次都对 getter 或 setter 进行烦人的调用。
readonly
字段只能在构造函数中设置。
可以在班级内随时设置
{get; private set;}
。
示例:
public class Car
{
public readonly string Name;
public string color {get; private set;}
public Car()
{
Name = "Car";
Color = "Red";
}
// will fail compilation
public void ModifyName()
{
Name = "Subaru"
}
// perfectly ok
public void ModifyColor()
{
Color = "Green"
}
}