6

There is sizeof() and typeof(), but why not a memberinfo() returning an instance of System.Reflection.MemberInfo for the part of code selected in order to aid in reflection code.

Example:

Program() 
{
       Type t = typeof(Foo);

       Foo foo = new Foo();
       PropertyInfo pi = memberinfo(Foo.Name) as PropertyInfo;
       // or shall it be like this
       // PropertyInfo pi = memberinfo(foo.Name) as PropertyInfo;

       string name = pi.GetValue(foo, null);
}

I am trying to understand if there is a fundamental reason why this could be implemented in the C# spec.

I am not bashing anything, I am just doing some wishful thinking, so be kind please.

John Alexiou
  • 28,472
  • 11
  • 77
  • 133
  • It could probably be implemented easily. I've wanted something like this too. Note that an alternate syntax would be required for methods, since they can be overloaded, so specifying the name alone would not be enough in that case. – cdhowie Nov 19 '10 at 21:38
  • You can create something similar using Expression Trees; this works particularly well for properties and fields. – Dan Bryant Nov 19 '10 at 21:49
  • @Bryant do you have an example or a link? – John Alexiou Nov 19 '10 at 21:57
  • Here's one: http://stackoverflow.com/questions/671968/retrieving-property-name-from-lambda-expression For a more in-depth look at extracting member information from expression trees, you might look at the Moq source code (they make extension use of lambda expressions to derive member information.) – Dan Bryant Nov 19 '10 at 22:32
  • I always wondered this, something similar, I mean compile time reflection! – nawfal Apr 02 '13 at 09:37
  • related: http://stackoverflow.com/questions/9335126/compile-time-reflection-in-c-sharp http://stackoverflow.com/questions/795208/extracting-property-names-for-reflection-with-intellisense-and-compile-time-che – nawfal Apr 02 '13 at 09:44

4 Answers4

8

Eric Lippert talks about this extensively on his blog

To quote directly from that post:

Just off the top of my head, here are a few {reasons why this hasn't been done}. (1) How do you unambiguously specify that you want a method info of an specific explicit interface implementation? (2) What if overload resolution would have skipped a particular method because it is not accessible? It is legal to get method infos of methods that are not accessible; metadata is always public even if it describes private details. Should we make it impossible to get private metadata, making the feature weak, or should we make it possible, and make infoof use a subtly different overload resolution algorithm than the rest of C#? (3) How do you specify that you want the info of, say, an indexer setter, or a property getter, or an event handler adder?

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Wesley Wiser
  • 9,491
  • 4
  • 50
  • 69
5

There are a couple of items which make this type of feature difficult. One of the primary ones being overloaded methods.

class Example { 
  public void Method() {}
  public void Method(int p1) {}
}

Which MethodInfo would the following return?

var info = memberinfo(Example.Method);

As Wesley has pointed out though, Eric Lippert's Blog has the full discussion on this issue.

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • 1
    Your example is a bit off, since `Type.GetMethod()` wouldn't work in this case either ... it throws an `AmbiguousMatchException`. While syntactic challenges exist to implement `infoof`, it would definitely make reflection-sensitive code a bit more maintainable. Whether `infoof` is sufficiently valuable compared to all other possible improvements to the C# language is another question entirely. – LBushkin Nov 19 '10 at 21:51
  • It could return an array with all the overloads. – John Alexiou Nov 19 '10 at 21:52
  • @LBushkin not sure how that makes my example off. It's pointing out the difficulties in disambiguating overloaded methods with the hypothetical feature `memberinfo`. – JaredPar Nov 19 '10 at 21:53
  • @jalexiou in what order? – JaredPar Nov 19 '10 at 21:53
  • @JaredPar in the same order as `.GetMethods()` would return. – John Alexiou Nov 19 '10 at 21:56
  • @jalexiou `GetMethods` returns methods in an undefined order. – JaredPar Nov 19 '10 at 21:58
  • @JaredPar: I don't disagree with the premise that disambiguating methods in such a syntax would be complicated and possibly confusing. I just think that better examples exist to illustrate that point - like the potential variance in resolution rules for public vs protected methods from normal overload resolution, for instance. – LBushkin Nov 19 '10 at 22:34
  • @LBushkin, my example is not meant to display that method overload is impossible or extremely complex but to point out it's not as simple as `methodinfo(Type.Name)` as the OP's post used – JaredPar Nov 19 '10 at 22:46
  • @JaredPar: Sure, I understand where you're coming from - and providing an example that addresses the OP's sample code is worthwhile. I guess I was just trying to point out that if basic overload resolution was the hardest problem to solve, we would probably already have an `infoof` operator. – LBushkin Nov 19 '10 at 22:53
1

There are numerous reasons why compile-time member reflection has not yet been implemented in C# - but most of them basically boil down to opportunity cost - there are many other languages features and enhancements that offer more benefit to more users. There's also the consideration that an infoof syntax could be complicated, confusing, and ultimately less powerful than using string-based reflection. It also wouldn't be a complete replacement for reflection since in many instances the metadata being manipulated isn't known at compile time.

However, all is not lost, there are a number of tricks that you can employ to perform slightly safer reflection that leverages capabilities of the C# language. For instance, we can take advantage of lambda expressions and expression trees to extract MemberInfo information. A simple example is:

public static class MethodExt {
    static MethodInfo MemberInfo(Action d) {
       return d.Method;
    }
    // other overloads ...
}

which works when you pass in a (non-anonymous) action delegate:

MethodInfo mi = MethodExt.MemberInfo( Object.ToString );

An implementation of the above using expression trees can more robust and flexible, but also substantially more complicated. It could be used to represent member and property access, indexers, etc.

The main issue with all such "fancy" approaches, is that they are confusing to developers who are used to seeing traditional reflection code. They also can't handle all cases, which often results in an unfortunate mixture of traditional reflection code and fancy expression tree code. Personally, while such techniques are interesting and inventive, it's probably best to avoid it in production code.

LBushkin
  • 129,300
  • 32
  • 216
  • 265
0

I myself use an approach that reads the IL from an anonymous method (using Mono.Reflection namespace) and grabs the info of the last token found in the anonymous method. This tends to be the only way to get information about things like the add_EventHandler or set_Property or captured local variables. To actual get properties I use expression trees.

The syntax that I use is Reflect.Member<T>.InfoOf<TMember>(Func<T,TMember> memberfunc) where Member is replaced with the type I'm interested in. It's verbose sure, but it lets a user know exactly what the code is trying to do. I also have Reflect.Member styles for things like statics and constructors. Here is the relevant code snippet::

internal static MemberInfo GetLastMemberOfType(MethodBase method, MemberTypes memberType)
    {
        var instructions = method.GetInstructions();
        var operandtype = memberType == MemberTypes.Field ? OperandType.InlineField : OperandType.InlineMethod; 
        for (int i = instructions.Count-1; i > -1 ; i--)
        {
            if (instructions[i].OpCode.OperandType == operandtype)
            {
                return instructions[i].Operand as MemberInfo;
            }
        }
        return null;
    }

Does it replace string based reflection? Absolutely not. Does it make my code safer while I'm refactoring interfaces and what not? Absolutely. Will it ship with the product I'm working on? Probably not.

Michael B
  • 7,512
  • 3
  • 31
  • 57