【问题标题】:c# struct cycled reference via genericc# struct 通过泛型循环引用
【发布时间】:2022-01-07 15:01:14
【问题描述】:

在定义结构时,很明显结构字段的值不能是结构本身。此外,当定义 2 个结构并且每个结构都具有另一个的字段类型时,问题实际上是相同的。

但是当不是直接设置类型 one 而是使用泛型而不是该类型时,为什么这仍然是个问题?

public struct Generic<T> { }
public struct Test1
{
  Generic<Test2> f;
}


public struct Test2
{
  Generic<Test1> f;
}

此代码编译良好并生成一个 dll。当我尝试加载 dll 时,我得到“无法加载一个或多个请求的类型..”并仅列出具有上述关系的那些类型。如果我只删除其中一个字段,则加载成功。发生了什么以及如何解决这个问题?

我还注意到,只要我有这个循环的泛型类型,dotnet 测试资源管理器就找不到任何测试,但我认为这是同样的问题。

编辑:

上面的代码可以编译成.dll文件。然后,从另一个项目中,我使用 System.Runtime.Loader 动态加载 dll:

public static void Main(string[] args)
{ 
  var context = new AssemblyLoadContext("context");
  Assembly assembly = context.LoadFromAssemblyPath("path-to-dll");
  Type[] types = assembly.GetTypes();
}

在示例的最后一行,我得到了 ReflectionTypeLoadException。

【问题讨论】:

  • “发生了什么事?”存储一个 Test2 需要多少字节?
  • 好吧,实际上没有,因为 Generic 是空的。但即使它有一些原语,大小也是已知的
  • 等等,什么? sharplab.io/… 这感觉就像一个错误。也许会提出问题github.com/dotnet/runtime
  • 更简单的情况Test1 { Generic&lt;Test1&gt; f; } 也失败了。
  • 我已经打开了github问题here

标签: c# generics struct dynamic-import


【解决方案1】:

我同意,这应该可行。但事实并非如此。这是一个known issue,运行时加载类型的方式。

解决这个问题显然需要重写如何加载类型的核心实现。导致行为发生重大变化,可能会影响大部分现有程序。到目前为止,解决此问题的成本被认为太高,无法证明这样做是合理的。

【讨论】:

  • 如果有人对用例感兴趣:
  • 我的回答错了,这绝对是对的。
  • 目标是将 IntPtr 存储到非托管结构中,并且泛型类型参数也具有其类型。还有一个带有 __makeref() 和 __refvalue() 未记录函数的 TypedReference,但它无法返回对给定结构的引用。使用 IntPtrs 和 Marshal/Unsafe 类这是可能的。请注意,这通常是不安全的,应仅在代码的时间关键部分使用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-07
  • 2012-01-02
  • 2016-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多