为什么结构体不能声明为 const?

发布于 2024-10-10 08:45:06 字数 566 浏览 2 评论 0原文

它们是堆栈上不可变的值类型。是什么让我不让它们成为常量?

参考文献:

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

z祗昰~ 2024-10-17 08:45:07

C# 中的 const 意味着它可以在编译时确定,这就是为什么只有非常原始的类型(例如 int 和 string)才可以是 const。

如果您有 C 背景,readonly 关键字可能更适合您。

Const in C# means it can be determined at compile time, which is why only very primitive types such as int and string can be a const.

If you are coming from a C background, the readonly keyword might better suit you.

┊风居住的梦幻卍 2024-10-17 08:45:07

为了让 C# 编译器生成结构类型的 const 值,它必须知道其所有字段中应包含哪些值。 C# 编译器本质上知道如何初始化某些类型(例如 Decimal)的字段,但对于大多数值类型,它没有这样的知识。

编译器可以提供一种在公开所有 struct 字段的上下文中声明结构类型常量值的方法。如果结构体的字段是私有,则只能在结构体中声明该类型的常量;如果字段是内部字段,则可以在程序集中的任何位置声明常量;如果public,它们可以在任何地方声明。

虽然我希望看到这样的功能,但我不希望有任何主流.net语言来实现它。编译器本身知道的类型的命名常量可以参与其他常量表达式,而静态只读变量则不能。如果 NumRows 是等于 4 的常量,则像 Arr[3*NumRows+7] 这样的表达式甚至可以用 Arr[19] 替换如果 NumRows 是在外部程序集中定义的。这使得此类常量比静态只读变量具有显着的优势。但是,如果常量属于编译器本质上无法识别的类型,则它参与任何常量表达式的能力将非常有限,从而首先有效地否定了其作为常量的优势。如果值类型常量具有公开字段,则编译器可以使用该字段的值作为常量,但由于 .net 语言的创建者在哲学上反对具有公开字段的结构,因此我不希望即使他们可以,他们也允许这种使用。

在某些潜在的用例中,常量比静态只读变量更受青睐,但许多此类情况可以使用现有类型进行可接受的处理。例如,库可能会公开 const Int64 来编码有关其版本的信息,并使用该值作为 GetLinkedVersionInfo 方法的默认参数值。有问题的值将在编译时“融入”调用代码中,从而允许该方法报告调用者链接的库版本,并可能确定其运行的版本是否存在兼容性问题。

For the C# compiler to produce a const value of a structure type it must know what values should go in all its fields. The C# compiler intrinsically knows how to initialize the fields of certain types like Decimal, but for most value types it has no such knowledge.

It would be possible for a compiler to provide a means of declaring constant values of a structure type in contexts where all of the struct fields were exposed. If a structure's fields were private, constants of that type could then be declared only within the structure; if the fields were internal, constants could be declared anywhere within the assembly; if public, they could be declared anywhere.

Although I would like to see such a feature, I do not expect any mainstream .net languages to implement it. Named constants of types the compiler inherently knows about can participate in other constant expressions, whereas static readonly variables cannot. If NumRows is a constant equal to 4, an expression like Arr[3*NumRows+7] can be replaced by Arr[19] even if NumRows is defined in an outside assembly. This gives such constants a substantial advantage over static readonly variables. If, however, a constant is of a type that a compiler does not intrinsically recognize, it would have very limited ability to participate in any constant expressions, effectively negating the advantage of its being a constant in the first place. If a value-type constant had an exposed field, it would be possible for a compiler to use the value of that field as a constant, but since the creators of .net languages are philosophically opposed to structures with exposed fields, I would not expect them to allow such usage even if they could.

There would be some potential use cases for favoring constants over static readonly variables, but many such cases can be handled acceptably using existing types. For example, a library might expose a const Int64 to encode information about its version, and use that value as a default parameter value for a GetLinkedVersionInfo method. The value in question would get "baked into" the calling code when it was compiled, thus allowing the method to report what version of the library the caller was linked with, and possibly identify whether there are any compatibility problems with the version it's running.

我最亲爱的 2024-10-17 08:45:07

我刚刚使用一个简单的可变结构测试了 readonly 关键字:

struct Test
{
   public int value;

   public void setInt(int val)
   {
      value = val;
   }
}

static class Program
{
   public static readonly Test t = new Test();

   static void Main()
   {
      Console.WriteLine(t.value); // Outputs "0"
      t.setInt(10);
      //t.value = 10;  //Illegal, will not let you assign field of a static struct
      Console.WriteLine(t.value); // Still outputs "0"
   }
}

尽管从技术上讲 readonly 结构不是编译时常量,但运行时不会让它改变。即使单步抛出了 setInt() 方法,它看起来像是值发生了变化,但没有显示 Main 中的变化。

我猜结构本身被放置在“只读”内存中,不允许它们更改。与类不同,类只是保持指针不变,允许类字段本身根据需要进行更改。

所以看起来static readonly实际上是一个const,即使对于可变结构也是如此。

I just tested the readonly keyword with a simple mutable struct:

struct Test
{
   public int value;

   public void setInt(int val)
   {
      value = val;
   }
}

static class Program
{
   public static readonly Test t = new Test();

   static void Main()
   {
      Console.WriteLine(t.value); // Outputs "0"
      t.setInt(10);
      //t.value = 10;  //Illegal, will not let you assign field of a static struct
      Console.WriteLine(t.value); // Still outputs "0"
   }
}

Even though a readonly struct isn't technicly a compile time constant, the runtime wont let it change. Even stepping threw the setInt() method it looks like value changes, but does not show the change in Main.

I guess the struct itself is placed in "readonly" memory, disallowing them to change. Unlike a class, which just keeps the pointer constant, allowing the class fields themselves to change as they wish.

So it appears static readonly is effectivly a const, even for mutable structs.

想念有你 2024-10-17 08:45:06

因为值类型构造函数可能会执行任何操作 - 例如,根据一天中的时间切换逻辑。常量值类型在理论上是有意义的,但在实践中它根本无法在自定义值类型上工作,因为构造函数可以灵活地做任何他们想做的事情。 (请记住,常量是在编译时计算的,这意味着您的构造函数必须在编译时运行。)

Because the value type constructor might do anything -- for example, switch logic based on the time of day. Constant value types makes sense intellectually, but it simply cannot work on custom value types in practice due to the flexibility of constructors to do whatever they please. (Remember that constants are evaluated at compile time, which means your constructor would have to be run at compile time.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文