如何检查类型是否为记录

15

有没有办法检查一个类型是一个记录?

class Program
{
    static void Main(string[] args)
    {
        IsRecord(typeof(Person)); // true
    }

    static bool IsRecord(Type type)
    {
        // ...
    }
}

public record Person
{
    public string LastName { get; }
    public string FirstName { get; }

    public Person(string first, string last) => (FirstName, LastName) = (first, last);
}

是的:type == typeof(Person) - jdweng
你是指 Type.IsValueType 吗? - JoelFan
1
@jdweng 的 type == typeof(Person) 无法检查 Person 类型的实际语义。OP 想知道如何确定一个类型是 C# 9 record 还是普通类。 - Eriawan Kusumawardhono
2
@JoelFan C# 9 记录类型 是引用类型。 - Joe Sewell
1个回答

10

这只是基于使用C# 9编译代码的一个快速查看。可能有更官方的方法来确定这一点。但从我所看到的,记录类型定义了一个名为<Clone>$的公共方法,否则它就不是一个有效的C#标识符。因此,如果一个类型具有这个方法,那么这个类型就是一个记录类型,除非有其他工具能够使用同样的名称重写IL。

var t = typeof(Person);
var isRecord = t.GetMethods().Any(m => m.Name == "<Clone>$");

我正要写这个答案...鉴于所有相关的“Type”属性具有与类类型相同的值,因此这是目前最好的选择。 - Camilo Terevinto
似乎是由Roslyn解决的语法糖问题,因为代码仍然需要遵守IL,并且这严格是C#的特性。 - Camilo Terevinto
实际上,似乎使用了一种“鸭子类型”,因为with语句正是使用了您回答中描述的Clone方法。因此,如果存在这样的方法,则足以被视为记录。 - Evk
从C# 10开始,“With”表达式也适用于所有值类型和匿名对象,尽管它们没有“<Clone>$”方法,因为它们不是记录,所以这个解决方案仍然可行。 - m1o2
4
@JoeSewell,这个方法在C# 10中引入的记录结构体中无法使用。"with"表达式在结构体中的实现方式不同,不需要一个"<clone>$"方法。 - m1o2
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接