以下是否有任何区别?
class C
{
// One:
public static readonly int ValueAsAMember = 42;
// Two:
public static int ValueAsAProperty { get { return 42; } }
}
我习惯以第一种方式编写常量(除非它们是私有/内部的,在这种情况下我使用const关键字),但我最近看到了第二种形式。
在可读性,约定,性能或其他方面,是否有任何优势?
答案 0 :(得分:29)
您有三种选择:
public static readonly int Value = 42;
public static Value { get { return 42; } }
public const Value = 42;
如果值在运行时不会更改,但在未来的代码版本中可能会更改,请选择static readonly
。
如果值可能在运行时更改,请选择属性。当然,如果您使用给定的代码,它将不会发生变化。
如果值实际上是一个在将来版本中甚至不会更改的常量(const
或Math.PI
),请选择int.MinValue
。当然,const
的使用受到值的类型的限制。
const
和static readonly
之间的区别在于const
值将在呼叫网站上被替换。如果在将来的版本中更改const
的值,则需要使用新值重新编译依赖于您的类的所有程序集。
该属性需要方法调用(调用getter是方法调用)。因此,如果值在运行时是常量,则不需要。
答案 1 :(得分:12)
是的,有一个优势:
如果值在将来的任何时候都可以更改(例如在代码的未来版本中),例如,在时间上,您可以在只读属性中支持改变你班级的公共界面。
如果必须用属性替换readonly
字段,则必须重新编译使用该类的任何其他程序集。
答案 2 :(得分:7)
有两个主要区别:
第一个是字段不能在接口上,而属性可以。因此,如果要在界面中使用它,则必须使用该属性。
第二个更有趣的是,readonly
字段可以被修改,而对象正在构建中。请使用以下代码:
public class MyTestClass
{
public readonly int MyInt = 1;
public MyTestClass()
{
MyInt = 2;
}
}
如果来电者
new MyTestClass().MyInt
它们将得到2.对于静态readonly
字段的静态构造函数也是如此。
答案 3 :(得分:3)
我看到它的方式,使用第一种方式更好地描述了价值的意图 - 这是不可变的。当一个人正在看课程时界面,他会看到该值是只读的,并且不必怀疑它是否可以在以后更改(因为在第二种情况下,他无法看到该属性的实现)。
关于const
声明的重要注意事项(我不相信readonly
的真实情况)是更改字段值会构成API更改即使您只是将值从42
更改为41
,也是如此。原因是对于consts
,值是在编译期间确定的,这意味着如果我编译一个使用你的常量的模块,并且你以后更改它,我将仍然使用旧值,直到我重新编译我的模块与您的新版本。
答案 4 :(得分:2)
答案 5 :(得分:1)
对我而言,主要优势在于readonly
您可以在代码中的任何位置声明它。但是,您将有机会仅将其设置为一次。使用setter,您可以一次声明并设置。
答案 6 :(得分:1)
我认为第一行使用readonly关键字使某些内容保持不变或者只是readonly。
并且第二行使用属性来实现readonly。两者都做同样但如果你与IL比较,属性会在dll中添加几行额外的代码。
答案 7 :(得分:0)
一个属性只是一个围绕字段的语法糖,一个没有设置器的属性被简单地声明为 readonly 字段,因此编译器将允许您将其设置为运行时,因为对于编译器,您引用的是只读字段。关于使用什么字段或属性有更多的讨论,这不在问题的范围之内。是的,它是您必须进行@SOreadytohelp引用的重新编译的语法糖。为了清楚起见,属性是一个为其创建了get和set方法的字段,C#将允许您像一个 字段一样引用它,而不是每次都对getter或setter进行烦人的调用。 / p>
答案 8 :(得分:0)
是的,两者之间有区别。
readonly
字段只能在构造函数中设置。
可以随时在班级内设置一个{get; private set;}
或简称为{get;}
(简称)。
示例:
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"
}
}