Generic parameter properties seem to have incorrect values, making them hard to compare #97

Closed
opened 2012-04-08 01:48:58 -05:00 by kg · 2 comments
kg commented 2012-04-08 01:48:58 -05:00 (Migrated from github.com)

I've been using the following logic for comparing two TypeReferences (since reference equality isn't adequate), and for most type references it works correctly (there are a few exceptions I know of that I already handle):

                if (
                    (target.Name == source.Name) &&
                    (target.Namespace == source.Namespace) &&
                    (target.Module == source.Module) &&
                    TypesAreEqual(target.DeclaringType, source.DeclaringType)
                )
                    return true;

In this case TypesAreEqual just maps to the function that performs this (and other) comparison(s).
AFAIK this has no false positives for any Mono.Cecil TypeReference, with the exception of GenericParameters.

For GenericParameters, however, the properties don't have values that I would expect.
Given the following two generic parameters:

            var gp1 = new GenericParameter("GP1", T1);
            var gp3 = new GenericParameter("GP1", T2);

The two parameters compare as the same. This is because they both have an empty Namespace (instead of, for example, the namespace of the type that declared the parameter), and they both have a null DeclaringType (instead of the type that declared the parameter). Worse still, they both have the same FullName - while I could imagine the DeclaringType and Namespace properties having the same value being intentional, I feel like these generic properties should absolutely have different FullNames (even though I try to avoid using FullName for comparisons because it creates garbage).

Thoughts? Is there a better way for me to do type comparisons that isn't vulnerable to this problem? Right now, I'm special-casing GenericParameter instances and directly comparing their Owners, but I hate having to have special code for each distinct class of TypeReference.

I've been using the following logic for comparing two TypeReferences (since reference equality isn't adequate), and for most type references it works correctly (there are a few exceptions I know of that I already handle): ``` csharp if ( (target.Name == source.Name) && (target.Namespace == source.Namespace) && (target.Module == source.Module) && TypesAreEqual(target.DeclaringType, source.DeclaringType) ) return true; ``` In this case TypesAreEqual just maps to the function that performs this (and other) comparison(s). AFAIK this has no false positives for any Mono.Cecil TypeReference, with the exception of GenericParameters. For GenericParameters, however, the properties don't have values that I would expect. Given the following two generic parameters: ``` csharp var gp1 = new GenericParameter("GP1", T1); var gp3 = new GenericParameter("GP1", T2); ``` The two parameters compare as the same. This is because they both have an empty Namespace (instead of, for example, the namespace of the type that declared the parameter), and they both have a null DeclaringType (instead of the type that declared the parameter). Worse still, they both have the same FullName - while I could imagine the DeclaringType and Namespace properties having the same value being intentional, I feel like these generic properties should absolutely have different FullNames (even though I try to avoid using FullName for comparisons because it creates garbage). Thoughts? Is there a better way for me to do type comparisons that isn't vulnerable to this problem? Right now, I'm special-casing GenericParameter instances and directly comparing their Owners, but I hate having to have special code for each distinct class of TypeReference.
jbevain commented 2012-04-08 03:10:22 -05:00 (Migrated from github.com)

There's not really any choice besides comparing all details of types : you can't compare an array type like you compare a generic parameter or a generic instantiation.

You can have a look at how the MetadataResolver handles it: https://github.com/jbevain/cecil/blob/master/Mono.Cecil/MetadataResolver.cs

There's not really any choice besides comparing all details of types : you can't compare an array type like you compare a generic parameter or a generic instantiation. You can have a look at how the MetadataResolver handles it: https://github.com/jbevain/cecil/blob/master/Mono.Cecil/MetadataResolver.cs
kg commented 2012-04-08 03:12:09 -05:00 (Migrated from github.com)

That's really useful, thanks. It might be worthwhile to have the GenericParameter's FullName include the FullName of the scope, though?

That's really useful, thanks. It might be worthwhile to have the GenericParameter's FullName include the FullName of the scope, though?
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gh-jbevain/cecil#97
No description provided.