Runtime: Portable mechanism needed to determine if two MemberInfos are backed by the same metadata definition

Created on 4 Feb 2016  路  9Comments  路  Source: dotnet/runtime

Currently, there is a hole in reflection whereby there's no straight-forward way to determine if:

1. MemberInfos differ only by ReflectedType (i.e. they are the same member, but one of them was obtained from a derived type.)

``` C#
public class C { public int F; }
public class D : C {}

static class Program {
static void Main(string[] args) {
var f1 = typeof(C).GetField("F");
var f2 = typeof(D).GetField("F");
System.Console.WriteLine(f1.Equals(f2)); // False
}
}

### 2. One MemberInfo is a generic instantiation of another.

``` C#
static class Program {
    static void Main(string[] args) {
        var m1 = typeof(List<>).GetMethod("Add");
        var m2 = typeof(List<int>).GetMethod("Add");

        // how to determine that m2 is instantiated from m1?
    }
}

On platforms that support the MetadataToken, this can be worked around by comparing the tokens, but without them, one has to resort to error-prone comparisons of the declaring type, name, and signature.

There should be a first-class portable way to address both.

Proposal for New API: HasSameMetadataDefinitionAs

Add a new API that determines if a member is backed/instantiated from the same metadata definition. In ECMA-335 terms, this is a member/type from the same module that has the same metadata def token. Platforms like .NET Native that do not keep around metadata tokens should still preserve enough information to answer this query portably.

``` C#
public class MemberInfo {
public virtual bool HasSameMetadataDefinitionAs(MemberInfo other);
...
}

A mostly correct implementation is:

``` C#
return Module.Equals(other.Module) && MetadataToken ==  other.MetadataToken;

But that ignores edge cases such as TypeInfo instances for array, byref, pointer, and type parameters types, which we'd need to spec and test.

api-approved area-System.Reflection

Most helpful comment

If I have e.g. two MethodInfo references and want to know if they have the same metadata definition, then whether this method is defined in terms of MethodInfo or MemberInfo won't make any difference to me, so as an API consumer I don't care.

If I have two MemberInfo references and want to know if they have the same metadata definition, then if it's defined in terms of MemberInfo I can use it, but otherwise I have to branch on a chain of is tests, so as an API consumer I'd prefer the former.

What advantage the more specific definition?

All 9 comments

cc @weshaggard

Microsoft.CSharp uses the MetadataToken workaround on platforms where it's available and does something random otherwise. This leads to different behaviors on AOT platforms where tokens are not available.

Needs to be primarily fixed for ProjectN/UWP.

@AtsushiKan @DnlHarvey does the API proposal above look reasonable? If yes, let's mark it so.

@nguerrera: I think HasSameMetadataDefinitionAs() is a good way to go but should be defined on the specific MemberInfos (Type, MethodInfo, etc.) with the properly constrained parameter type.

If I have e.g. two MethodInfo references and want to know if they have the same metadata definition, then whether this method is defined in terms of MethodInfo or MemberInfo won't make any difference to me, so as an API consumer I don't care.

If I have two MemberInfo references and want to know if they have the same metadata definition, then if it's defined in terms of MemberInfo I can use it, but otherwise I have to branch on a chain of is tests, so as an API consumer I'd prefer the former.

What advantage the more specific definition?

I agree with @JonHanna. Why can't this be polymorphic?

Defining the api polymorphically means every caller pays the penalty of comparing the "MemberTypes" and casting to the specific type. Parameter types should also be as specific as possible for better compile time bug detection.

How frequent is the use case where the caller doesn't already know the specific type? There is no case where MemberInfos of different flavors will be considered "equivalent" by this api.

API review:
@weshaggard mentioned this would have been very useful in the past. Partners are likely asking for it.

We like the original proposal (as virtual) - approved. If there are reasons to do something else, please speak up = reply with clear proposal change and defend it.

BTW: We discussed as well having overloads with specific types - mainly for performance. We do not think it is a must have right now. We can consider it later.

Marking as up for grabs
Complexity: Medium-Hard (requires deep reflection knowledge - all cases need to be covered)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

matty-hall picture matty-hall  路  3Comments

yahorsi picture yahorsi  路  3Comments

sahithreddyk picture sahithreddyk  路  3Comments

bencz picture bencz  路  3Comments

Timovzl picture Timovzl  路  3Comments