getter 与只读

问题描述 投票:0回答:9

以下有什么区别吗?

class C
{
    // One:
    public static readonly int ValueAsAMember = 42;

    // Two:
    public static int ValueAsAProperty { get { return 42; } }
}

我习惯用第一种方式编写常量(除非它们是私有/内部的,在这种情况下我使用

const
关键字),但我最近看到了第二种形式。

在可读性、约定、性能或其他方面,一种方式比另一种方式有什么优势吗?

c# getter readonly
9个回答
39
投票

您有三个选择:

  • 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就是方法调用)。因此,如果该值在运行时是恒定的,则不需要这样做。


15
投票

是的,有一个优点:

如果该值在未来的任何时候(例如在代码的未来版本中)可以更改,例如,以时间相关的方式更改,您可以在只读属性中支持该更改,而无需更改您班级的公共接口。

如果必须用属性替换

readonly
字段,则必须重新编译使用您的类的任何其他程序集。


9
投票

有两个主要区别:

首先,字段不能位于接口上,而属性可以。所以如果你想在界面中使用它,你必须使用该属性。

第二个更有趣的是,在构造对象时可以修改

readonly
字段。采取以下代码:

public class MyTestClass
{
    public readonly int MyInt = 1;

    public MyTestClass()
    {
        MyInt = 2;
    }
}

如果来电者这样做

new MyTestClass().MyInt

他们将得到 2。静态

readonly
字段的静态构造函数也是如此。


3
投票

我认为,使用第一种方式更好地描述了值的意图 - 即它是不可变的。当一个人查看类的接口时,他会看到该值是只读的,并且不必怀疑以后是否可以更改(因为在第二种情况下,他看不到属性的实现) .

关于

const
声明需要注意的一个重要事项(我不认为对于
readonly
来说是这样),更改字段的值构成 API 更改,即使您只是将值从
42
更改为
 41
。原因是,对于
consts
,该值是在编译时确定的,这意味着如果我编译一个使用您的常量的模块,并且您稍后更改它,我仍将使用旧值,直到我重新编译我的模块你的新版本。


2
投票

readonly
非常适合用于只能在构造函数中更改的内容。当您遵循 TDD 模式时,典型的服务作为接口就是这样的示例。

在你的例子中

const
是最好的,毕竟它是一个常数。

只读

常量

干杯


1
投票

我认为第一行使用 readonly 关键字使某些内容保持不变或只读。

第二行是利用属性来实现只读。两者的作用相同,但如果与 IL 进行比较,该属性会向 dll 添加几行额外的代码。


1
投票

对我来说主要的优点是

readonly
你可以在代码中的任何地方声明它。但是,您将有机会仅设置它一次。使用 setter,您可以一键声明和设置。


0
投票

属性只是字段周围的语法糖,没有设置器的属性只是声明为只读字段,因此编译器将允许您在构造函数中的运行时设置它,因为对于您正在引用的编译器一个 readonly 字段。关于如何使用字段或属性有一个更大的讨论,这不在问题的范围内。是的,你必须重新编译 @SOreadytohelp 引用的这个语法糖。需要明确的是,属性是一个为其创建了 get 和 set 方法的字段,C# 将允许您像字段一样引用它,而不是每次都对 getter 或 setter 进行烦人的调用。


0
投票

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

	
© www.soinside.com 2019 - 2024. All rights reserved.