Two questions regarding the new records feature :
How do I recognize a record using reflection ? looking [here][1] maybe there
is a way to detect the EqualityContract
but I am not sure if that is the way to go ?
Is it possible to have a generic constraint that a generic type is a record ? that is if it is possible to indicate that type parameter T must be a record class using a constraint ?
- How do I recognize a record using reflection ?
If you try record classes in sharplab.io
you'll see that record classes are usual classes that implement IEquatable<T>
interface and contain additional members that are used to compare and clone instances of the record class. There is no special attributes that indicate that the class is a record class
.
So I guess that there is no way to determine if a class is a record class using reflection.
looking here maybe there is a way to detect the
EqualityContract
but I am not sure if that is the way to go ?
It is possible to determine using reflection if a class has such property, but this is not a 100% guarantee that the class with such property is a record class.
- Is it possible to have a generic constraint that a generic type is a record ? that is if it is possible to indicate that type parameter T must be a record class using a constraint ?
It is not possible.
T
must be a record class.Champion records
page you'll learn that there is no way to specify something like where T : record
in C# 9
. Moreover there are plans to eliminate any meaningful semantic difference between a record and a class in C# 10
. So that records' features like with
will be available for classes too. Adding record
constraint will make this goal not achievable.As a 'hack', all records have a synthesized method <Clone>$
which you can look for. Since you can't write a method with that name in C#, a class with a <Clone>$
member is guaranteed to be a record as of C# 9.
However there is no guarantee that this will continue to be the case. For example it's possible that in C# 10.0 some records won't have a <Clone>$
member, or that some non-records will.
public static bool IsRecord(Type type) => type.GetMethod("<Clone>$") != null;
As mentioned by everyone else, it's not possible to write
private void MyFunc<T>(T t) where T : record {...}
You can however create a record which you then have every record type you create inherit from. This will pretty much achieve what you are asking, although, I don't know how I feel about it...
public abstract record RecordMarker;
public record MyRecord : RecordMarker;
public void MyFunc<T>(T t) where T : RecordMarker
{
}
With this you can only pass record types in since classes cannot inherit from records.
MyFunc(new MyRecord()); // Works
MyFunc(new MyClass()); // Compiler Error
How do I recognize a record using reflection ?
As pointed out here and here
There is not only not an official way to do this, it is explicitly against the design of the feature. The intent for records is that, hopefully with C# 10, we'll get to a point where making a class a record is purely a convenience choice, and that every other part of the feature will be achievable through some form of syntax. It should not be a breaking change to change a type from a record to a class, and we even imagine that an IDE refactoring could automatically move a type to and from record syntax without clients noticing. For C# 9 there are some places where we didn't quite achieve this, but that's the goal.
Despite the above there are still scenarios where checking for record us useful. Some hackish ways to detect records which work ATM are:
EqualityContract
property with the CompilerGenerated
attributeisRecord = ((TypeInfo)t).DeclaredProperties.Where(x => x.Name == "EqualityContract").FirstOrDefault()?.GetMethod?.GetCustomAttribute(typeof(CompilerGeneratedAttribute)) is object;
<Clone>$
member as pointed out by @Yair HalberstadtisRecord = t.GetMethod("<Clone>$") is object;
or a combination of both
Is it possible to have a generic constraint that a generic type is a record ?
No
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With