C# record ToString() 导致堆栈溢出并停止调试 session 并出现奇怪的错误

标签 c# c#-9.0

我编写了一个单元测试,并使用新的 C# 记录来存储一些测试所需的数据。单元测试运行良好,但是当我设置断点并将鼠标移到记录变量名称上时,调试 session 结束并且我收到一条看起来很奇怪的错误消息。

为了向 Microsoft 报告问题,我编写了一个简单的单元测试来演示问题,但除此之外没有多大意义:

#nullable enable
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace CSharpRecordTest {

  record Twin(string Name) {
    public Twin? OtherTwin { get; set; }
  }

  [TestClass]
  public class UnitTest1 {
    [TestMethod]
    public void TestMethod1() {
      var twinA = new Twin("A");
      var twinB = new Twin("B");
      twinA.OtherTwin = twinB;
      twinB.OtherTwin = twinA;
      Assert.AreEqual(twinA, twinA.OtherTwin.OtherTwin);
    }
  }
}

测试运行正常,但是当在 Assert.AreEqual( 处设置断点并将鼠标移到 twinA 上时,调试 session 停止并显示此错误消息:

enter image description here

最佳答案

我花了一两天时间才弄清楚发生了什么,因为调试器没有让我看到任何东西。我写了一个控制台应用程序:

class Program {
  record Twin(string Name) {
    public Twin? OtherTwin { get; set; }
  }

  static void Main(string[] args) {
    var twinA = new Twin("A");
    var twinB = new Twin("B");
    twinA.OtherTwin = twinB;
    twinB.OtherTwin = twinA;
    Console.WriteLine(twinA);
  }
}

控制台应用程序也遇到了麻烦,但至少它显示了堆栈溢出以及它导致的行:

Console.WriteLine(twinA);

堆栈看起来像这样(虽然更复杂):

twinA.OtherTwin.OtherTwin.OtherTwin.OtherTwin.OtherTwin.OtherTwin...OtherTwin.ToString()

问题是编译器自动编写的 ToString() 会在每个属性上再次调用 .ToString()。

如果一条记录引用了自身或其他引用了第一条记录的记录,ToString() 将失败并且需要与 Equals()、GetHashCode() 以及更多(我没有尝试过)一起被覆盖。

实际上,当有一个非只读的属性时,Equals() 和 GetHashCode() 应该被覆盖,否则像 Dictionary 这样的类将无法工作。

有关详细信息,请参阅我在 CodeProject 上的文章:C# 9 Record: Compiler Created ToString() Code can Lead to Stack Overflow and Worse

关于C# record ToString() 导致堆栈溢出并停止调试 session 并出现奇怪的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67285095/

相关文章:

c# - 使用 FindLast 之类的方法时如何区分找到的 0 和默认值(int)?

c# - String.join 来自最后一个元素的数组

c# - 如何使用 LINQ to SQL 将单行添加到列表?

c# - 从引用中删除版本号(避免 "Could not load file or assembly..."错误)?

c# - 具有集合属性的记录类型和具有值语义的集合

c# - C# 中的 Regex.Split 命令

c# - .NET 6 中的 using 语句/指令在哪里

c# - 组合属性 setter "init and private"(C#9)

位置记录 : should be disabled? 中的 StyleCopAnalyzers/SA1313

asp.net-core-webapi - .NET 5.0 Web API 不适用于具有所需属性的记录