kof*_*fus 14 c# c#-9.0 record-classes
关于新记录功能的两个问题:
如何使用反射识别记录?看 [here][1] 也许有一种方法可以检测到,EqualityContract但我不确定这是否可行?
是否可以有一个泛型约束,即泛型类型是记录?也就是说,是否可以使用约束指示类型参数 T 必须是记录类?
Ili*_*hev 12
- 如何使用反射识别记录?
如果您尝试使用记录类,sharplab.io您将看到记录类是实现IEquatable<T>接口并包含用于比较和克隆记录类实例的附加成员的常用类。没有特殊属性表明该类是record class.
所以我想没有办法使用反射来确定一个类是否是一个记录类。
看这里,也许有一种方法可以检测到,
EqualityContract但我不确定这是否可行?
可以使用反射来确定类是否具有此类属性,但这并不能 100% 保证具有此类属性的类是记录类。
- 是否可以有一个泛型约束,即泛型类型是记录?也就是说,是否可以使用约束指示类型参数 T 必须是记录类?
这不可能。
T必须是记录类的任何信息。Champion records您将了解到无法指定类似where T : recordin 的内容C# 9。此外,还计划消除C# 10. 这样记录的功能with也将可用于类。添加record约束将使这个目标无法实现。作为“黑客”,所有记录都有一个<Clone>$您可以查找的合成方法。由于您不能在 C# 中编写具有该名称的方法,因此<Clone>$保证具有成员的类是C# 9的记录。
然而,不能保证这种情况会继续下去。例如,在 C# 10.0 中,某些记录可能没有<Clone>$成员,或者某些非记录有成员。
public static bool IsRecord(Type type) => type.GetMethod("<Clone>$") != null;
Run Code Online (Sandbox Code Playgroud)
正如其他人所提到的,不可能写
private void MyFunc<T>(T t) where T : record {...}
Run Code Online (Sandbox Code Playgroud)
但是,您可以创建一个记录,然后您创建的每个记录类型都继承自该记录。这几乎可以实现您的要求,尽管我不知道我对此有何感觉......
public abstract record RecordMarker;
public record MyRecord : RecordMarker;
public void MyFunc<T>(T t) where T : RecordMarker
{
}
Run Code Online (Sandbox Code Playgroud)
有了这个,您只能传入记录类型,因为类不能从记录继承。
MyFunc(new MyRecord()); // Works
MyFunc(new MyClass()); // Compiler Error
Run Code Online (Sandbox Code Playgroud)
如何使用反射识别记录?
不仅没有官方的方法可以做到这一点,而且它明确违背了该功能的设计。记录的目的是,希望通过 C# 10,我们能够达到将类设为记录纯粹是一种方便的选择,并且该功能的所有其他部分都可以通过某种形式的语法来实现。将类型从记录更改为类不应该是重大更改,我们甚至可以想象 IDE 重构可以自动将类型移至记录语法或从记录语法移出类型,而无需客户注意。对于 C# 9,有些地方我们没有完全实现这一目标,但这就是目标。
尽管存在上述情况,但在某些情况下检查记录仍然很有用。一些检测 ATM 工作记录的黑客方法是:
EqualityContract具有该属性的CompilerGenerated属性isRecord = ((TypeInfo)t).DeclaredProperties.Where(x => x.Name == "EqualityContract").FirstOrDefault()?.GetMethod?.GetCustomAttribute(typeof(CompilerGeneratedAttribute)) is object;
Run Code Online (Sandbox Code Playgroud)
<Clone>$@Yair Halberstadt 指出的成员isRecord = t.GetMethod("<Clone>$") is object;
Run Code Online (Sandbox Code Playgroud)
或两者的组合
是否可以有一个泛型约束,即泛型类型是一条记录?
不