c# - 为什么泛型结构不能具有在 C# 中指定泛型类型的静态成员?

标签 c# generics struct typeloadexception

如果这是重复的,我们深表歉意!我四处搜寻但找不到解释。当我尝试实例化该结构时,下面的玩具示例就会给我一个 TypeLoadException 。如果我使用类或者不在静态成员中指定泛型类型(将其保留为 T),它就可以正常工作。

public struct Point<T>
{
    static Point<int> IntOrigin = new Point<int>(0, 0);

    T X { get; }
    T Y { get; }

    public Point(T x, T y)
    {
        this.X = x;
        this.Y = y;
    }
}

我的实际情况更为复杂,可以归结为这样的事情,所以我真的很想了解为什么它会发出 TypeLoadException。

最佳答案

This comment ,和another comment ,在 Github 上最接近解决当前的事态,指出为什么这种自引用结构定义尚未被允许,并且在可预见的 future 可能不会被允许。

即使静态成员也需要先初始化类型,然后才能将其包含在类型布局中,但类型初始化需要初始化该静态成员。此初始化依赖项循环会创建导致运行时异常的 Catch-22。

根据this comment ,.NET Core 可以很好地适应这种模式。但是当我在 .NET Core 项目中尝试你的示例时,我发现了同样的失败。因此,要么该注释有误,要么实例成员场景和静态成员场景之间存在一些细微的差异(我没有费心去进一步调查)。

有趣的是,dotNETFiddle.net 上使用的编译器会发出编译时错误 "Struct member 'struct2 field' of type 'struct1' causes a cycle in the struct layout" 。我不知道为什么 Visual Studio 编译器似乎不再产生此错误(在 2017 年和 2019 年检查过)。对我来说,这似乎是另一个错误。但是 Github 上围绕这个问题的讨论似乎承认该代码在技术上是有效的(即根据 C# 规范),因此可能在某个时候有意识地决定删除编译器错误,并让 CLR 在运行时。

请注意,错误引用页面中的建议建议更改为 class而不是struct 。当然,这通常是不可行的,其中 struct正在使用;拥有一个值类型可能很重要。然而,在您的具体示例中,实际上有一个基于该想法的简单解决方法。由于您的字段不是 struct实例的实际布局的一部分,您可以将其移动到专门用于此类值的静态类。例如:

public struct Point<T>
{
    public static class Constants
    {
        static Point<int> IntOrigin = new Point<int>(0, 0);
    }

    T X { get; }
    T Y { get; }

    public Point(T x, T y)
    {
        this.X = x;
        this.Y = y;
    }
}

然后代替(例如)Point<double>.IntOrigin ,您需要使用Point<double>.Constants.IntOrigin 。由于每个类型的类型初始化可以独立完成,因此不会出现初始化循环,代码运行良好。

关于c# - 为什么泛型结构不能具有在 C# 中指定泛型类型的静态成员?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63856813/

相关文章:

c# - Entity Framework 核心线程安全吗?

c++ - 显式专门化通用函数是快速的

c - 重新分配结构会导致堆损坏

c - 当函数的指针存储在结构体中时如何调用函数

C Incompatible pointer type 消息似乎列出了预期和实际的相同指针类型

c# - 在 C# 中使用 .Add 的二维数组

c# - 是否有标准的 C# 库,例如用于 java 的 Apache commons?

c# - 有没有一种方法可以在 C# 中将内插字符串拆分为多行,同时在性能方面在运行时执行相同的操作

java - 为什么java循环通用规范不允许将 "this"转换为通用实例

c# - 如何为学生和多门类(class)成绩创建字典?