Req15: GetType for instances, methods and properties


[This post is part of a series, “wish-list for future versions of VB“]


 


IDEA: GetType should work on instances.


    ‘ Currently we can get the System.Type of a named type


    Dim t As Type = GetType(IEnumerable(Of ))


 


    ‘ We’d also like to get the compile-time System.Type of a given expression


    Dim x As IEnumerable(Of Integer) = {1, 2, 3}


    Dim t1 As Type = GetType(x)  ‘ returns IEnumerable(Of Integer), the compile-time type


    Dim t2 As Type = x.GetType() ‘ returns Integer(), the run-time type


 


    ‘ this doesn’t evaluate the expression: it merely figures out its compile-time type:


    Dim t As Type = GetType(New C)


 


 


    Dim t As Type = GetType(Me)  ‘ returns the compile-time type of “Me”


    Dim t As Type = GetType(MyClass)  ‘ for shared methods, returns the type of the class/module we’re in


 


IDEA: GetType should be able to return stuff about a given method/property, or the current method/property. For instance,


    ‘ We’d also like to get the Reflection.MethodInfo of a specified method


    Dim m As Reflection.MethodInfo = GetType(AddressOf Console.WriteLine(x))


 


    ‘ The expression isn’t evaluated: it’s merely used to resolve which overload


    Dim m As Reflection.MethodInfo = GetType(AddressOf Call (New C).f(15 * Factorial(2)))


 


    ‘ A common need is to get the name of the current method


    Dim m As Reflection.MethodInfo = GetType(AddressOf MyMethod)


 


 


    ‘ Likewise for properties, events, fields


    Dim p As Reflection.PropertyInfo = GetType(AddressOf c.p)


    Dim e As Reflection.EventInfo = GetType(AddressOf c.e)


    Dim f As Reflection.FieldInfo = GetType(AddressOf c.f)


 


    ‘ And the current property:


    Dim m As Reflection.MethodInfo = GetType(AddressOf MyProperty)


 


This idea has been frequently discussed and requested, e.g. here in Eric Lippert’s blog. What has sunk the idea every single time is that getting a decent syntax for the feature is just so hard. One of the big problems with syntax is overloads, as in the Console.WriteLine example above. One approach is to invent a wholly new syntax which lets you write method signatures inside the GetType operator. Another approach, as I’ve taken here, is to write just a normal invocation expression — except it’s not invoked; it’s merely used as a well-understood syntax for specifying which overload we want.


 


But all of the above examples can already be implemented today with a fairly decent workaround and recognizable syntax:


    Dim minfo = GetMethodInfo(Sub() f())


    Dim pinfo = GetPropertyInfo(Function() p)


    Dim tinfo = GetTypeInfo(Me)


    Dim current_minfo = Reflection.MethodBase.GetCurrentMethod()


    Dim current_pinfo = GetPropertyInfo(Reflection.MethodBase.GetCurrentMethod())


 



    Function GetMethodInfo(f As Expressions.Expression(Of Action)) As Reflection.MethodInfo


        Return DirectCast(f.Body, Expressions.MethodCallExpression).Method


    End Function


 


    Function GetPropertyInfo(Of T)(ByVal f As Expressions.Expression(Of Func(Of T))) As Reflection.MemberInfo


        Return DirectCast(f.Body, Expressions.MemberExpression).Member


    End Function


 


    Function GetPropertyInfo(ByVal minfo As Reflection.MemberInfo) As Reflection.PropertyInfo


        Return (From p In minfo.DeclaringType.GetProperties() Where p.GetAccessors().Contains(minfo)).FirstOrDefault


    End Function


 


    Function GetTypeInfo(Of T)(ByVal x As T) As System.Type


        Return GetType(T)


    End Function


 


 


Provisional evaluation from VB team: The current workarounds do everything that’s needed, and their syntax is familiar. There doesn’t seem need to invent any new syntax for this. If anything, the Power6: __CALLER_MEMBER__ idea was neater than any of these proposals.


 


 


 

Comments (5)

  1. Kevin Ryall says:

    The only real requirement I have in this area is to be able to get the name of methods and parameters (as well as types) at compile time – it would make validation / logging SO much easier. The reflection option is not appropriate in these cases as it is too expensive – I can’t risk someone using a slow name lookup on a method which may be evaluated in a tight loop.

    What I want to be able to do is use the method or parameter name in code and have the comopiler resolve it for maximum runtime efficiency – for example:

    AssertNonNull(surname, NameOf(surname))

    or…

    Log(“entering method {0}”, NameOf(Method))

    Something like this would massively simplify a lot of my validation and logging code.

  2. The one thing the workarounds really don’t address is getting hold of an event at compiled time – currently this is only possible via reflection.

    Also – it seems to me that the workarounds defer problems to run time and wherever possible, it’s better for these things to fail at compile time if possible.

  3. Dzonny says:

    I like to be able to get Reflection object for Type (already have GetType), Method, Property, Event, Argument, Field (have I forgotten something?). Because we often need only name of such object, special syntax to get name of the object makes sense – and it can be translated to string in compile-time. Also Property/Event delegates may be helpful. Main advantage of having such operators rather than passing string somewhere (Me.GetType.GetProperty("Item")) is that it is compiler-checked and thus refactoring-safe.

    Making GetType accept expression is not very important for me.

  4. Kyralessa says:

    I like the idea of having a consistent syntax: Knowing that you can type GetType on *anything* and have it "just work".

  5. weitzhandler says:

    Idea 1 (GetType(reference)) – Good ieda

    Idea 2 (GetType(method) returns MethodInfo) looks too dangerous to me

Skip to main content