@@ -816,6 +816,8 @@ private bool ComputeIsRecord()
816816 var metadata = module . metadata ;
817817 var typeDef = metadata . GetTypeDefinition ( handle ) ;
818818
819+ bool isRecord = false ;
820+
819821 bool getEqualityContract = isStruct ;
820822 bool toString = false ;
821823 bool printMembers = false ;
@@ -824,25 +826,46 @@ private bool ComputeIsRecord()
824826 bool opEquality = false ;
825827 bool opInequality = false ;
826828 bool clone = isStruct ;
827- foreach ( var methodHandle in typeDef . GetMethods ( ) )
829+
830+ // Consider inherited properties as well: check for an EqualityContract property.
831+ foreach ( var prop in this . GetProperties ( ) )
828832 {
829- var method = metadata . GetMethodDefinition ( methodHandle ) ;
830- if ( metadata . StringComparer . Equals ( method . Name , "Clone" ) )
833+ if ( prop . Name == "EqualityContract" && prop . Getter != null )
834+ {
835+ getEqualityContract = true ;
836+ break ;
837+ }
838+ }
839+
840+ // Consider inherited members as well: use GetMethods() which includes inherited methods
841+ // via the GetMembersHelper. This ensures methods like ToString/PrintMembers from
842+ // base types satisfy the record shape requirements.
843+ foreach ( var m in this . GetMethods ( ) )
844+ {
845+ string name = m . Name ;
846+ // error CS8859: Members named 'Clone' are disallowed in records.
847+ if ( name == "Clone" )
831848 {
832- // error CS8859: Members named 'Clone' are disallowed in records.
833849 return false ;
834850 }
835851
836- getEqualityContract |= metadata . StringComparer . Equals ( method . Name , "get_EqualityContract" ) ;
837- toString |= metadata . StringComparer . Equals ( method . Name , "ToString" ) ;
838- printMembers |= metadata . StringComparer . Equals ( method . Name , "PrintMembers" ) ;
839- getHashCode |= metadata . StringComparer . Equals ( method . Name , "GetHashCode" ) ;
840- equals |= metadata . StringComparer . Equals ( method . Name , "Equals" ) ;
841- opEquality |= metadata . StringComparer . Equals ( method . Name , "op_Equality" ) ;
842- opInequality |= metadata . StringComparer . Equals ( method . Name , "op_Inequality" ) ;
843- clone |= metadata . StringComparer . Equals ( method . Name , "<Clone>$" ) ;
852+ // Also accept a getter method named get_EqualityContract
853+ getEqualityContract |= ( name == "get_EqualityContract" ) ;
854+ toString |= ( name == "ToString" ) ;
855+ printMembers |= ( name == "PrintMembers" ) ;
856+ getHashCode |= ( name == "GetHashCode" ) ;
857+ equals |= ( name == "Equals" ) ;
858+ opEquality |= ( name == "op_Equality" ) ;
859+ opInequality |= ( name == "op_Inequality" ) ;
860+ clone |= ( name == "<Clone>$" ) ;
861+
862+ isRecord = getEqualityContract & toString & printMembers & getHashCode & equals & opEquality & opInequality & clone ;
863+ if ( isRecord )
864+ {
865+ break ;
866+ }
844867 }
845- return getEqualityContract & toString & printMembers & getHashCode & equals & opEquality & opInequality & clone ;
868+ return isRecord ;
846869 }
847870 #endregion
848871 }
0 commit comments