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


当前回答

使用只读没有明显的性能好处,至少我在任何地方都没有看到过。这只是为了完全按照你的建议去做,为了在初始化后防止修改。

因此,它是有益的,因为它可以帮助您编写更健壮、更可读的代码。当您在团队中工作或进行维护时,这样的事情会带来真正的好处。将某些东西声明为只读类似于在代码中为该变量的使用订立契约。你可以把它看作是用与其他关键字(如internal或private)相同的方式添加文档,你在说“这个变量在初始化后不应该被修改”,而且你在强制执行它。

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

其他回答

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

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

Readonly可以在声明时初始化,也可以只从构造函数中获取它的值。与const不同,它必须同时进行初始化和声明。 Readonly拥有const所拥有的一切,再加上构造函数初始化

代码https://repl.it/HvRU/1

using System;

class MainClass {
    public static void Main (string[] args) {

        Console.WriteLine(new Test().c);
        Console.WriteLine(new Test("Constructor").c);
        Console.WriteLine(new Test().ChangeC()); //Error A readonly field 
        // `MainClass.Test.c' cannot be assigned to (except in a constructor or a 
        // variable initializer)
    }


    public class Test {
        public readonly string c = "Hello World";
        public Test() {

        }

        public Test(string val) {
          c = val;
        }

        public string ChangeC() {
            c = "Method";
            return c ;
        }
    }
}

使用只读没有明显的性能好处,至少我在任何地方都没有看到过。这只是为了完全按照你的建议去做,为了在初始化后防止修改。

因此,它是有益的,因为它可以帮助您编写更健壮、更可读的代码。当您在团队中工作或进行维护时,这样的事情会带来真正的好处。将某些东西声明为只读类似于在代码中为该变量的使用订立契约。你可以把它看作是用与其他关键字(如internal或private)相同的方式添加文档,你在说“这个变量在初始化后不应该被修改”,而且你在强制执行它。

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

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

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

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

Robert Pickering写了一篇关于不变性的好处的博客文章。这篇文章可以在这里或archive.org上找到。

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

例如,在csharpdepth的代码中:

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在保护字段单例不被初始化两次方面起着很小的作用。另一个细节是,对于上述场景,您不能使用const,因为const强制在编译时创建,而单例在运行时创建。