【问题标题】:Array declaration as class field vs local variable [duplicate]数组声明作为类字段与局部变量[重复]
【发布时间】:2021-06-04 10:06:50
【问题描述】:

我知道这是一个基本问题,但似乎没有明确的答案。 将数组声明为类字段时,不允许在运行时确定变量大小,

public class MyClass : MonoBehaviour{

    int size = 6;
    float[] f = new float[size]; //not allowed

    // Start is called before the first frame update
    void Start()
    {
      //some code
    }
}

虽然以相同的方式声明它,但作为函数内部的局部变量,例如开始非常好:

public class MyClass : MonoBehaviour{

    void Start()
    {
        int size = 6;
        float[] f = new float[size];

        //some code
    }
}

这与变量的范围有关吗?或者内存分配发生在堆栈、堆等的地方? 提前谢谢你

【问题讨论】:

  • 我相信当您声明为成员变量时,会引发编译时错误,说明 A field initializer cannot reference the non-static field, method, or property。错误本身说明了编译错误的原因。现在,如果要声明为字段,则将大小定义为const,以便大小值仅在编译时可用...将int size = 6 更改为const int size = 6
  • 当然你可以改变数组字段的大小如果你在构造函数中初始化它,而不是试图用字段声明本身来初始化它。你需要区分声明和初始化。
  • 感谢您的回答。我知道解决方法(使用 List 而不是数组,将其声明为 const 等)。我正在寻找的是关于推理的见解,为什么 C# 会允许它在“开始”函数中。此外,根据另一篇文章,似乎在构造函数中进行内联初始化和初始化似乎对于允许的内容和不允许的内容没有区别stackoverflow.com/questions/24551/…
  • 类字段在static上下文中初始化,因为它发生在之前构造函数被调用,所以this还不存在,因此你不能引用任何东西那是基于实例的..只有其他static的东西

标签: c# unity3d


【解决方案1】:

这个有明确的答案,你可以在specification找到它:

实例字段的变量初始化器不能引用正在创建的实例。因此,在变量初始化器中引用this 是编译时错误,因为变量初始化器通过simple_name 引用任何实例成员是编译时错误。在示例中:

class A
{
    int x = 1;
    int y = x + 1;        // Error, reference to instance member of this
}

y 的变量初始化器会导致编译时错误,因为它引用了正在创建的实例的成员。

【讨论】:

    【解决方案2】:

    根据docs “与 System.Collections 命名空间中的类不同,Array 具有固定容量。要增加容量,您必须创建一个具有所需容量的新 Array 对象,将元素从旧 Array 对象复制到新对象,然后删除旧数组。”

    编译错误CS0236“实例字段不能用于初始化方法外的其他实例字段” + 实例字段初始化spec 解释问题。

    出于同样的原因,您不能这样做:

        int int1 = 3;
        int int2 = int1;
    

    【讨论】:

    • “这就是为什么你不能用变量设置数组的大小,会抛出编译错误。” 但是第二个 sn-p 设置数组大小变量(并且工作得很好)
    • 感谢您的回答。我知道数组被设计为默认为静态 DS 并且不允许变量作为数组的大小是有意义的——这就是 List 类的目的——但是为什么在“开始”函数中允许它呢?我的问题是更好地理解 C# 和 Unity 的内存模型,而不是简单地找到解决方案让它工作。
    • 没错,我更新了答案。它是 c# 的东西,而不是统一的
    • "另一方面,变量的初始化顺序没有保证,因此编译器可以重新排列这些变量,因此在运行时不能保证 size 会在 float[] f 之前初始化,所以你会被认为有 NullReferenceException" 这是非常错误的。 int 无法得到您 NullReferenceException,并且 “变量初始化程序按照它们出现在类声明中的文本顺序执行”,如语言 spec 中所述。
    • 所以初始化的顺序是有保证的。
    猜你喜欢
    • 1970-01-01
    • 2014-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-23
    • 2023-03-05
    • 1970-01-01
    相关资源
    最近更新 更多