Last weekend, as I was polishing off Service Locator 2, I was reminded how Reflection returns properties as methods, as well as as properties. Take this simple class as an example:

public class MyClass
{
    private string myText_;
 
    public string MyText
    {
        get { return this.myText_; }
        set { this.myText_ = value; }
    }
 
    public void DoStuff()
    {
    }
}

Since MSIL has no concept of properties, the C# compiler converts the MyText property to two methods named get_MyText and set_MyText, respectively. How many elements are then in this list?

BindingFlags flags = BindingFlags.Public | 
    BindingFlags.Instance | 
    BindingFlags.DeclaredOnly;
 
List<MethodInfo> methods = 
    new List<MethodInfo>(typeof(MyClass).GetMethods(flags));

If you answered 3, you were correct: The three methods returned are indeed get_MyText, set_MyText, and DoStuff (since I specified the DeclaredOnly flag I don't get all the inherited methods). Here's a relatively elegant way to get only the real methods:

List<MethodInfo> methods = 
    new List<MethodInfo>(typeof(MyClass).GetMethods(flags));
methods.RemoveAll(delegate(MethodInfo mi) 
{
    return mi.IsSpecialName; 
});

The IsSpecialName property returns true if the method has a special name, which is exactly the case if the method in reality is the implementation of a property or event. This filtered list of methods contains exactly one method: The DoStuff method.

Filtering the result of GetMembers is very similar:

List<MemberInfo> members =
    new List<MemberInfo>(typeof(MyClass).GetMembers(flags));
members.RemoveAll(delegate(MemberInfo mi)
{
    MethodInfo method = mi as MethodInfo;
    if (method != null)
    {
        return method.IsSpecialName;
    }
    return false;
});

As the RemoveAll method now takes a Predicate<MemberInfo> (since it is a list of MemberInfo elements), it's now necessary to first examine whether the MemberInfo is a method or something else.

How many elements are in this list of members? The correct answer is 3, since the default constructor is also returned together with the DoStuff method and the MyText property.