4

This is a followup to this question: Lambda expression not returning expected MemberInfo

class Human
{
    public string name { get; set; }
}

class Man : Human
{

}

var m1 = typeof(Human).GetProperty("name");
var m2 = typeof(Man).GetProperty("name");

//m1 != m2 why?

The same holds for MethodInfos.

I can understand there has to be a difference when Human is an interface, or when name of Human is abstract/virtual. But why is it so for sealed types? Isn't name of Man exactly name of Human?

Clarification: As Jon says their ReflectedTypes are different. ReflectedType in equality should come handy when deciding equality of interface members or overridden members since they are different. But I don't think it should be considered for deciding equality of simple cases like above. May be the design team wanted to be consistent. Just wondering what rationale drove framework designers to consider ReflectedType property in deciding equality of same member spanning over multiple classes.

Community
  • 1
  • 1
nawfal
  • 70,104
  • 56
  • 326
  • 368

1 Answers1

7

They differ in their ReflectedType property:

The ReflectedType property retrieves the Type object that was used to obtain this instance of MemberInfo. This may differ from the value of the DeclaringType property if this MemberInfo object represents a member that is inherited from a base class.

So if you print out m1.ReflectedType, it should print Human. If you print out m2.ReflectedType, it should print Man.

EDIT: In terms of why the equality operator is implemented this way: it's always a delicate design decision to work out what == should mean, in the case where there may be distinguishable but not "primary" differences between objects. This is where providing different IEqualityComparer implementations is useful, but of course that doesn't work for the operators themselves.

In general, if x == y is true then it's quite unusual for x.Foo to be different to y.Foo for any property. I can't immediately think of any cases where that occurs in the framework.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Jon, I understand that, and they may differ in many other aspects, but my question is more like why did C#/.NET team decide it to be so. I will make my question clear – nawfal Apr 29 '13 at 10:27
  • 1
    @nawfal: I guess there are situations in which it's useful to know which type was asked for the information. I'm not sure that they *will* differ in many other aspects, to be honest. If your question is really "why does `ReflectedType` exist?" then that's very different. – Jon Skeet Apr 29 '13 at 10:30
  • 1
    One more point: http://startbigthinksmall.wordpress.com/2008/12/10/retrieving-the-base-definition-for-a-propertyinfo-net-reflection-mess/ – Ani Apr 29 '13 at 12:18
  • @JonSkeet, its indeed useful to know their reflected type, but I don't know why is it considered in equality. I think `m1 = new MemberInfo { Name = "name", ReflectedType = Human }` should have been equal to `m2 = new MemberInfo { Name = "name", ReflectedType = Man }` – nawfal Apr 29 '13 at 12:19
  • @nawfal: So now your question is really about the implementation of the overloaded `==` operator? (Again, that wasn't clear - I thought it was about it not just returning references to the same objects...) – Jon Skeet Apr 29 '13 at 12:34
  • Why do you expect those to be equal? It's like saying `new AppleInBasket{Apple = redApple, Basket = basket1}` and `new AppleInBasket{Apple = redApple, Basket = basket2)` should be equal because they both contain a red apple. – CodeCaster Apr 29 '13 at 12:36
  • @JonSkeet that was actually my intention; sure I had not worded it properly. – nawfal Apr 29 '13 at 12:36
  • @CodeCaster that depends on the domain isn't it? If we are talking *purely* about apples, does it matter if it comes in basket1 or basket2? I think that is the case here, hence my question. You can make an answer if you think it is not (which is exactly what I am asking). – nawfal Apr 29 '13 at 12:39
  • 1
    @nawfal: See my edit. Out of interest, can you think of examples where `==` returns true for distinguishable values? The only thing I can think of offhand is +0 and -0 for floating point structs... I can't think of a similar example for classes. – Jon Skeet Apr 29 '13 at 12:42
  • @nawfal no, because you ask an `AppleInBasket` object whether it is the same as another instance, and that object's equality comparer does take the basket into account. It just works like that, as does `MemberInfo`. If your question then is _"Why is that so"_, then please do ask that. :-) – CodeCaster Apr 29 '13 at 12:44
  • @JonSkeet I can't in the framework, but I am sure ppl often write domain models like this where two models may differ in many aspects, but will be equal (based on Id, Name etc). – nawfal Apr 29 '13 at 12:44
  • @nawfal: But `MemberInfo` is in the framework :) What I'm saying is that if it *did* behave the way you're expecting it to, it would be the only class in the framework that did so, as far as I'm aware. I think more people would be surprised by that than by the current behaviour. – Jon Skeet Apr 29 '13 at 12:48
  • @CodeCaster //and that object's equality comparer does take the basket into account.// It would if that's what your domain logic demands. Thats what I said already, that it depends on what the logic is. The question is exactly what you put in your next sentence" *why is that so?* That whether this domain (the memberinfo thing) is equivalent to what you have in your mind (apple in basket case), which is what Jon is trying hard to explain. – nawfal Apr 29 '13 at 12:51
  • @JonSkeet that point on *examples where == returns true for distinguishable values* was an eyeopener. Will accept this for that :) – nawfal Apr 29 '13 at 12:53