最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c# - Hash keys match, but Distinct() doesn't remove duplicates with my custom MemberInfo type class only when the Member

programmeradmin5浏览0评论

I got tired of dealing with properties and fields separately so I made a VariableInfo strategy pattern to handle both without having to know what type it is. You feed the context a FieldInfo or a PropertyInfo and it makes a VariableInfo out of it. I've also made VariableInfo extend MemberInfo. There are extensions for pulling a type's fields and properties and returning all of them as VariableInfo objects (GetAllVariables()). Here is a part of the class definition (check this github repo for complete definition of all classes I describe here)

  public class VariableInfo : MemberInfo
    {
        //InfoParent has 2 children. One for fields and one for properties.
        private InfoParent variable;
        public VariableInfo(PropertyInfo pi) 
        {
            variable = new VariableProperty(pi);
        }
        public VariableInfo(FieldInfo fi)
        {
            variable = new VariableField(fi);
        }
        //mi is the internally stored PropertyInfo or FieldInfo. With this set, Attribute.IsDefined does not work for properties (solved in previous question linked below)
        //NOTE: when I talk about "PASSTHROUGH", this next commented line is active and the other MemberType is commented out.
        //public override MemberTypes MemberType => variable.mi.MemberType;
        //updated to this to fix the Attribute.IsDefined bug:
        public override MemberTypes MemberType => MemberTypes.Custom;
        ...
    }

In my previous question, Ivan figured out that in order to get Attribute.IsDefined to work, the MemberType in the VariableInfo class needed to point to MemberTypes.Custom. This avoids a cast that doesn't work in the BCL source code. Unfortunately, that had a very unexpected result... Linq queries no longer work. Doing a variables.Distinct() doesn't remove duplicates. When stepping into the Distinct, you can see the hash codes for the duplicate variables MATCH, but it doesn't remove the duplicates. When I revert the change, it works again.

Visual (Code is in the linked repo) - The GetAllVariables_CUSTOM() uses the MemberType set to custom and the passthrough one points to the internal PropertyInfo/FieldInfo object.

So the questions are...

  1. Why?
  2. Is there a way around this without breaking Attribute.IsDefined?

NOTE: The GetAllVariables() method iterates up the base types to make sure it gets everything. That's why there are duplicates. Doing a GetProperties() on a PropertyInfo, even with the BindingFlags set to include both public and non-public variables, will excludes private variables in parent classes. Same thing goes for fields.

I got tired of dealing with properties and fields separately so I made a VariableInfo strategy pattern to handle both without having to know what type it is. You feed the context a FieldInfo or a PropertyInfo and it makes a VariableInfo out of it. I've also made VariableInfo extend MemberInfo. There are extensions for pulling a type's fields and properties and returning all of them as VariableInfo objects (GetAllVariables()). Here is a part of the class definition (check this github repo for complete definition of all classes I describe here)

  public class VariableInfo : MemberInfo
    {
        //InfoParent has 2 children. One for fields and one for properties.
        private InfoParent variable;
        public VariableInfo(PropertyInfo pi) 
        {
            variable = new VariableProperty(pi);
        }
        public VariableInfo(FieldInfo fi)
        {
            variable = new VariableField(fi);
        }
        //mi is the internally stored PropertyInfo or FieldInfo. With this set, Attribute.IsDefined does not work for properties (solved in previous question linked below)
        //NOTE: when I talk about "PASSTHROUGH", this next commented line is active and the other MemberType is commented out.
        //public override MemberTypes MemberType => variable.mi.MemberType;
        //updated to this to fix the Attribute.IsDefined bug:
        public override MemberTypes MemberType => MemberTypes.Custom;
        ...
    }

In my previous question, Ivan figured out that in order to get Attribute.IsDefined to work, the MemberType in the VariableInfo class needed to point to MemberTypes.Custom. This avoids a cast that doesn't work in the BCL source code. Unfortunately, that had a very unexpected result... Linq queries no longer work. Doing a variables.Distinct() doesn't remove duplicates. When stepping into the Distinct, you can see the hash codes for the duplicate variables MATCH, but it doesn't remove the duplicates. When I revert the change, it works again.

Visual (Code is in the linked repo) - The GetAllVariables_CUSTOM() uses the MemberType set to custom and the passthrough one points to the internal PropertyInfo/FieldInfo object.

So the questions are...

  1. Why?
  2. Is there a way around this without breaking Attribute.IsDefined?

NOTE: The GetAllVariables() method iterates up the base types to make sure it gets everything. That's why there are duplicates. Doing a GetProperties() on a PropertyInfo, even with the BindingFlags set to include both public and non-public variables, will excludes private variables in parent classes. Same thing goes for fields.

Share Improve this question edited Mar 18 at 1:57 A person asked Mar 18 at 1:40 A personA person 798 bronze badges 1
  • Please share a minimal reproducible example (it needs to be in the question, not a separate github repo). My guess is your Equals implementation is wrong. Put a breakpoint in your Equals and step into it and see what it is doing. – mjwills Commented Mar 18 at 2:35
Add a comment  | 

1 Answer 1

Reset to default 1

Because of the following code:

if (variable.MemberType != other.MemberType)
    return false;

variable.MemberType is the actual member type, but other.MemberType is always MemberTypes.Custom, so this comparison always fails.

Perhaps what you want is variable.MemberType != other.variable.MemberType?

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论