C# 是否为继承的只读字段赋值?

C# 是否为继承的只读字段赋值?,c#,inheritance,constructor,readonly,C#,Inheritance,Constructor,Readonly,所以我有一个有很多孩子的基类。这个基类定义了一些具有默认值的只读属性和变量。根据孩子的不同,这些可能会有所不同 只读属性/字段允许您更改构造函数内变量的值和定义,但不允许更改其他内容。如果我试图更改子类构造函数中继承的只读变量的值,则会出现“只读变量只能在构造函数中赋值”错误。为什么会这样?我如何在没有思考的情况下解决这个问题 我的意图是:允许用户通过脚本进行扩展,在脚本中用户只能更改某些字段一次。原因是您只能在该类的构造函数中分配只读字段。 根据(我的重点): 当字段声明包含只读修饰符时,对该

所以我有一个有很多孩子的基类。这个基类定义了一些具有默认值的只读属性和变量。根据孩子的不同,这些可能会有所不同

只读属性/字段允许您更改构造函数内变量的值和定义,但不允许更改其他内容。如果我试图更改子类构造函数中继承的只读变量的值,则会出现“只读变量只能在构造函数中赋值”错误。为什么会这样?我如何在没有思考的情况下解决这个问题


我的意图是:允许用户通过脚本进行扩展,在脚本中用户只能更改某些字段一次。

原因是您只能在该类的构造函数中分配只读字段。
根据(我的重点):

当字段声明包含只读修饰符时,对该声明引入的字段的赋值只能作为声明的一部分或在同一类的构造函数中发生

要解决这个问题,可以在基中创建一个受保护的构造函数,该构造函数接受只读属性的参数

例如:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Base b = new Child();
            Console.WriteLine(b.i);
            Console.Read();
        }
    }

    class Base
    {
        public readonly int i;

        public Base()
        {
            i = 42;
        }

        protected Base(int newI)
        {
            i = newI;
        }
    }

    class Child : Base
    {
        public Child()
            : base(43)
        {}
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Base b = new Child();
            Console.WriteLine(b.I);
            Console.Read();
        }
    }

    class Base
    {
        public int I { get; protected set; }

        public Base()
        {
            I = 42;
        }
    }

    class Child : Base
    {
        public Child()
        {
            I = 43;
        }
    }
}

这在设计上是不可能的。尝试将值传递给受保护的基类构造函数

您可以通过使用虚拟的仅获取属性来获得所需的确切行为

public class BSE
{
    virtual public int Prop 
    {
        get
        {
            return 6;
         }
     }
}
public class Derived : BSE
{
    public override int Prop
    {
         get
         {
             return 10;
         }
    }
 }

字段位于继承和重载模型之外,不应用于提供多态特性。

Adam给出了正确答案。如果您担心它将占用的空间(构造函数中的参数数量?),那么您应该用不同的解决方案解决这个问题:创建一个BaseConfig类,它包含所有这些属性,这就是需要传入的全部内容。Base然后可以从BaseConfig的属性中分配所有的只读字段,或者让Base只保留一个BaseConfig类型的只读字段,并参考该字段获取值


至于原因,请参阅关于何时初始化/初始化每个类的只读字段。

您可以将属性与公共get访问器和受保护的set访问器一起使用。派生类可以设置此属性的值

例如:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Base b = new Child();
            Console.WriteLine(b.i);
            Console.Read();
        }
    }

    class Base
    {
        public readonly int i;

        public Base()
        {
            i = 42;
        }

        protected Base(int newI)
        {
            i = newI;
        }
    }

    class Child : Base
    {
        public Child()
            : base(43)
        {}
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Base b = new Child();
            Console.WriteLine(b.I);
            Console.Read();
        }
    }

    class Base
    {
        public int I { get; protected set; }

        public Base()
        {
            I = 42;
        }
    }

    class Child : Base
    {
        public Child()
        {
            I = 43;
        }
    }
}

这听起来更像;但它仍然是一个相当大的跳跃,从干净的
公共只读int number=5
@Ruirize您要给一个只读字段分配一个常量?这听起来像是对只读字段的滥用,你可能想用虚拟属性来代替;我希望有一个非常好的方法来实现这个,这样为我的引擎编写脚本就会非常整洁和聪明。哦,好吧。BaseConfig类也可以工作,谢谢!此解决方案的唯一缺点是,它不允许您计算要传递给基类的值。@Kent:可以通过在基类构造函数的参数列表中调用静态方法来实现。看,我有一个非常类似的问题,并且得到了一个允许你向一个成员分配一个任务的。功能上是只读的,所有样板代码都在一个位置。
受保护的
不是只读的。派生类可以在其构造函数之外设置它。