備忘録
原因不明の不具合に悩まされ、調べたら C# 言語仕様だったということがあったためメモ。
record の override method は class のそれと違う動作をする。
using System; public class Class1 { public string PropC1 = "PropC1"; public override string ToString() => "Class1"; } public class Class2 : Class1 { public string PropC2 = "PropC2"; } public record Record1 { public string PropR1 = "PropR1"; public /* sealed */ override string ToString() => "Record1"; } public record Record2 : Record1 { public string PropR2 = "PropR2"; } Console.WriteLine($"{new Class1()}"); Console.WriteLine($"{new Class2()}"); Console.WriteLine($"{new Record1()}"); Console.WriteLine($"{new Record2()}");
結果 ... class と record で出力が違う!
Class1 // Class1 .ToString() was called. Class1 // Class1 .ToString() was called. Record1 // Record1.ToString() was called. Record2 { PropR1 = PropR1, PropR2 = PropR2 } // object .ToString() was called! Why?
record の (unsealed) override method を派生 record から呼んだ場合、直近の基底 record の method ではなく、最基底 record (つまり object) の method が適用される。
特に .ToString() はユーザ定義した基底 record の method が呼ばれなくて罠になる。解らなくて半日悩んだ。
record は拡張版 class ではなかったかと ...
このあたりの issue に関連しているか。
[Proposal]: Records with sealed base ToString override · Issue #4174 · dotnet/csharplang · GitHub