Skip to content
This repository has been archived by the owner on Nov 1, 2020. It is now read-only.

Commit

Permalink
Switch over to the .NETCore Attribute.Equals() behavior. (#3552)
Browse files Browse the repository at this point in the history
This ports dotnet/coreclr#6240 over to Project N.

The TL;DR version of the change is "private fields in base classes are no
longer disregarded by Equals()/GetHashCode()".

In fact, changing ExposeToDerivedClasses() to return true always is sufficient
to effect the desired change. The rest of the delta is just the result of
constant-folding and dead-coding from that point.

[tfs-changeset: 1657635]
  • Loading branch information
dotnet-bot authored and atsushikan committed May 8, 2017
1 parent 6de5237 commit f0ce17b
Showing 1 changed file with 13 additions and 11 deletions.
24 changes: 13 additions & 11 deletions src/System.Private.CoreLib/src/System/Attribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ public abstract partial class Attribute
{
protected Attribute() { }

//
// Compat note: .NET Core changed the behavior of Equals() relative to the full framework:
//
// (https://github.com/dotnet/coreclr/pull/6240)
//
// This implementation implements the .NET Core behavior.
//
public override bool Equals(Object obj)
{
if (obj == null)
Expand Down Expand Up @@ -124,7 +131,7 @@ public override int GetHashCode()
// This non-contract method is known to the IL transformer. See comments around _ILT_ReadFields() for more detail.
//
[CLSCompliant(false)]
protected virtual int _ILT_GetNumFields(bool inBaseClass)
protected virtual int _ILT_GetNumFields()
{
return 0;
}
Expand All @@ -133,20 +140,15 @@ protected virtual int _ILT_GetNumFields(bool inBaseClass)
// This non-contract method is known to the IL transformer. The IL transformer generates an override of this for each specific Attribute class.
// Together with _ILT_GetNumFields(), it fetches the same field values that the desktop would have for comparison.
//
// The desktop uses "GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)" to determine the list of fields
// used for comparison. Unfortunately, this list can include fields that the "this" class has no right to access (e.g. "internal"
// .NET Core uses "GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly)" to
// determine the list of fields used for comparison. Unfortunately, this list can include fields that the "this" class has no right to access (e.g. "internal"
// fields in base classes defined in another assembly.) Thus, the IL Transformer cannot simply generate a method to walk the fields and
// be done with it. Instead, _ILT_ReadFields() directly fetches only the directly declared fields and reinvokes itself non-virtually on its
// base class to get any inherited fields. To simplify the IL generation, the generated method only writes the results into a specified
// offset inside a caller-supplied array. Attribute.ReadFields() calls _ILT_GetNumFields() to figure out how large an array is needed.
//
// The "inBaseClass" determines whether the "this" is the "this" that Equals/GetHashCode was actually called or one of its base types.
// That's because the list of fields includes directly declared private fields but not inherited private fields. (This can in turn
// cause weird effects like the derived type returning "true" for Equals() while it's base type's Equal() returns "false" - but that's
// backward compat for you.)
//
[CLSCompliant(false)]
protected virtual void _ILT_ReadFields(Object[] destination, int offset, bool inBaseClass)
protected virtual void _ILT_ReadFields(Object[] destination, int offset)
{
}

Expand All @@ -156,9 +158,9 @@ protected virtual void _ILT_ReadFields(Object[] destination, int offset, bool in
//
private Object[] ReadFields()
{
int numFields = _ILT_GetNumFields(inBaseClass: false);
int numFields = _ILT_GetNumFields();
Object[] fieldValues = new Object[numFields];
_ILT_ReadFields(fieldValues, 0, inBaseClass: false);
_ILT_ReadFields(fieldValues, 0);
return fieldValues;
}
}
Expand Down

0 comments on commit f0ce17b

Please sign in to comment.