在 C# 中将字段标记为“只读”有什么好处?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/277010/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 21:12:59  来源:igfitidea点击:

What are the benefits to marking a field as `readonly` in C#?

c#readonlyprocessing-efficiencymemory-efficient

提问by leora

What are the benefits of having a member variable declared as read only? Is it just protecting against someone changing its value during the lifecycle of the class or does using this keyword result in any speed or efficiency improvements?

将成员变量声明为只读有什么好处?它只是防止有人在类的生命周期中更改其值,还是使用此关键字会导致任何速度或效率改进?

采纳答案by Bill the Lizard

The readonlykeyword is used to declare a member variable a constant, but allows the value to be calculated at runtime. This differs from a constant declared with the constmodifier, which must have its value set at compile time. Using readonlyyou can set the value of the field either in the declaration, or in the constructor of the object that the field is a member of.

readonly关键字用于将成员变量声明为常量,但允许在运行时计算该值。这与使用const修饰符声明的常量不同,后者必须在编译时设置其值。使用readonly您可以在声明中或在该字段所属的对象的构造函数中设置该字段的值。

Also use it if you don't want to have to recompile external DLLs that reference the constant (since it gets replaced at compile time).

如果您不想重新编译引用常量的外部 DLL(因为它在编译时被替换),也可以使用它。

回答by Xiaofu

There are no apparent performance benefits to using readonly, at least none that I've ever seen mentioned anywhere. It's just for doing exactly as you suggest, for preventing modification once it has been initialised.

使用 没有明显的性能优势readonly,至少我在任何地方都没有看到过。这只是为了完全按照您的建议进行操作,以防止在初始化后进行修改。

So it's beneficial in that it helps you write more robust, more readable code. The real benefit of things like this come when you're working in a team or for maintenance. Declaring something as readonlyis akin to putting a contract for that variable's usage in the code. Think of it as adding documentation in the same way as other keywords like internalor private, you're saying "this variable should not be modified after initialisation", and moreover you're enforcingit.

所以它的好处在于它可以帮助您编写更健壮、更易读的代码。当您在团队中工作或进行维护时,此类事情的真正好处就来了。声明一些东西readonly类似于在代码中为该变量的使用签订合同。将其视为以与其他关键字(如internalor )相同的方式添加文档private,您是在说“初始化后不应修改此变量”,而且您正在强制执行它。

So if you create a class and mark some member variables readonlyby design, then you prevent yourself or another team member making a mistake later on when they're expanding upon or modifying your class. In my opinion, that's a benefit worth having (at the small expense of extra language complexity as doofledorfer mentions in the comments).

因此,如果您创建一个类并按readonly设计标记一些成员变量,那么您可以防止您自己或其他团队成员稍后在扩展或修改您的类时犯错误。在我看来,这是一个值得拥有的好处(以 doofledorfer 在评论中提到的额外语言复杂性为代价)。

回答by JaredPar

I don't believe there are any performance gains from using a readonly field. It's simply a check to ensure that once the object is fully constructed, that field cannot be pointed to a new value.

我认为使用只读字段不会带来任何性能提升。它只是一个检查,以确保一旦对象完全构造,该字段就不能指向新值。

However "readonly" is very different from other types of read-only semantics because it's enforced at runtime by the CLR. The readonly keyword compiles down to .initonly which is verifiable by the CLR.

然而,“只读”与其他类型的只读语义非常不同,因为它是由 CLR 在运行时强制执行的。readonly 关键字编译为 .initonly,CLR 可以验证它。

The real advantage of this keyword is to generate immutable data structures. Immutable data structures by definition cannot be changed once constructed. This makes it very easy to reason about the behavior of a structure at runtime. For instance, there is no danger of passing an immutable structure to another random portion of code. They can't changed it ever so you can program reliably against that structure.

这个关键字的真正优点是生成不可变的数据结构。根据定义,不可变数据结构一旦构造就不能更改。这使得在运行时推断结构的行为变得非常容易。例如,将不可变结构传递给代码的另一个随机部分是没有危险的。他们永远无法更改它,因此您可以针对该结构进行可靠的编程。

Here is a good entry about one of the benefits of immutability: Threading

这是关于不变性的好处之一的很好的条目:线程

回答by Daniel Auger

To put it in very practical terms:

用非常实际的术语来说:

If you use a const in dll A and dll B references that const, the value of that const will be compiled into dll B. If you redeploy dll A with a new value for that const, dll B will still be using the original value.

如果您在 dll A 中使用 const 并且 dll B 引用该 const,则该 const 的值将被编译到 dll B 中。如果您使用该 const 的新值重新部署 dll A,则 dll B 仍将使用原始值。

If you use a readonly in dll A and dll B references that readonly, that readonly will always be looked up at runtime. This means if you redeploy dll A with a new value for that readonly, dll B will use that new value.

如果您在 dll A 和 dll B 引用中使用只读,则该只读将始终在运行时查找。这意味着如果您使用该只读的新值重新部署 dll A,则 dll B 将使用该新值。

回答by Brian Rasmussen

Keep in mind that readonly only applies to the value itself, so if you're using a reference type readonly only protects the reference from being change. The state of the instance is not protected by readonly.

请记住, readonly 仅适用于值本身,因此如果您使用的是引用类型, readonly 只会保护引用不被更改。实例的状态不受只读保护。

回答by Michael

Be careful with private readonly arrays. If these are exposed a client as an object (you might do this for COM interop as I did) the client can manipulate array values. Use the Clone() method when returning an array as an object.

小心私有只读数组。如果这些将客户端公开为对象(您可以像我一样为 COM 互操作执行此操作),则客户端可以操作数组值。将数组作为对象返回时使用 Clone() 方法。

回答by Kristof Verbiest

There is a potential case where the compiler can make a performance optimization based on the presence of the readonly keyword.

有一种潜在的情况,编译器可以根据 readonly 关键字的存在进行性能优化。

This only applies if the readonly field is also marked as static. In that case, the JIT compiler can assume that this static field will never change. The JIT compiler can take this into account when compiling the methods of the class.

这仅适用于 readonly 字段也标记为static 的情况。在这种情况下,JIT 编译器可以假设这个静态字段永远不会改变。JIT 编译器在编译类的方法时可以考虑到这一点。

Typical example: your class could have a static readonly IsDebugLoggingEnabledfield that is initialized in the constructor (e.g. based on a configuration file). Once the actual methods are JIT compiled, the compiler may ommit whole parts of the code when debug logging is not enabled.

典型示例:您的类可能具有在构造函数中初始化的静态只读IsDebugLoggingEnabled字段(例如,基于配置文件)。一旦实际方法被 JIT 编译,编译器可能会在未启用调试日志记录时忽略代码的全部部分。

I have not checked if this optimization is actually implemented in the current version of the JIT compiler, so this is just speculation.

这个优化我没有查过当前版本的JIT编译器是否真的实现了,所以这只是猜测。

回答by Adam Naylor

Don't forget there is a workaround to get the readonlyfields set outside of any constructors using outparams.

不要忘记有一种解决方法可以readonly使用out参数在任何构造函数之外设置字段。

A little messy but:

有点乱,但是:

private readonly int _someNumber;
private readonly string _someText;

public MyClass(int someNumber) : this(data, null)
{ }

public MyClass(int someNumber, string someText)
{
    Initialise(out _someNumber, someNumber, out _someText, someText);
}

private void Initialise(out int _someNumber, int someNumber, out string _someText, string someText)
{
    //some logic
}

Further discussion here: http://www.adamjamesnaylor.com/2013/01/23/Setting-Readonly-Fields-From-Chained-Constructors.aspx

进一步讨论:http: //www.adamjamesnaylor.com/2013/01/23/Setting-Readonly-Fields-From-Chained-Constructors.aspx

回答by Shane

There can be a performance benefit in WPF, as it removes the need for expensive DependencyProperties. This can be especially useful with collections

WPF 可以带来性能优势,因为它消除了对昂贵的 DependencyProperties 的需求。这对集合特别有用

回答by Yuriy Zaletskyy

Another interesting part of usage of readonly marking can be protecting field from initialization in singleton.

使用只读标记的另一个有趣的部分是保护字段免于在单例中初始化。

for example in code from csharpindepth:

例如在来自csharpindepth 的代码中:

public sealed class Singleton
{
    private static readonly Lazy<Singleton> lazy =
        new Lazy<Singleton>(() => new Singleton());

    public static Singleton Instance { get { return lazy.Value; } }

    private Singleton()
    {
    }
}

readonly plays small role of protecting field Singleton from being initialized twice. Another detail is that for mentioned scenario you can't use const because const forces creation during compile time, but singleton makes creation at run time.

readonly 起到保护字段 Singleton 不被两次初始化的小作用。另一个细节是,对于上述场景,您不能使用 const,因为 const 在编译时强制创建,但单例在运行时创建。