Question

Imports System.Reflection
Public Class Test
    Private Field As String
End Class

Module Module1
    Sub Main()

        Dim field = GetType(Test).GetField("Field", Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance)

        Dim test = New Test

        Dim GetValue = New Func(Of Test, String)(Function(t As Test) field.GetValue(test))

        'This line indicates a compile error: 'Expression does not produce a value':
        Dim SetValue = New Action(Of Test, String)(Function(t As Test, value As String) field.SetValue(test, value))
    End Sub
 End Module


Module Module2
    Dim field = GetType(Test).GetField("Field", Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance) 'Is Shared (Module)
    Sub Main2()
        Dim test = New Test
        Dim GetValue = New Func(Of Test, String)(Function(t As Test) field.GetValue(test))
        Dim SetValue = New Action(Of Test, String)(Function(t As Test, value As String) field.SetValue(test, value))
    End Sub
End Module

Donno what's wrong but Module2 works just great!

Was it helpful?

Solution

EDIT Scratch my original answer, I misread the problem.

The reason this does not compile is an issue of type inference and late binding. In the first example field is a local variable and hence can participate in type inference. The compiler will correctly deduce the type to be FieldInfo. This means the SetValue call is a statically typed call. It is a void returning method and is hence incompatible with a Function lambda expression which requires a return value.

The field value in the second example though is declared at a module level. These variables are not subject to type inference and hence the type object will be chosen. Since the type is object, the SetValue call becomes a late bound call. All late bound calls are assumed to point to a function that has a return type of Object. At runtime if the function returns void, Nothing will actually be returned. So in this context it is a non-void returning expression and hence compiles.

One option you have to work around this is to explicitly type field as Object in the first example. This will force it to be a late bound call and it will compile just like the second one

Dim field As Object = ...

OTHER TIPS

Well here is the final answer based on JaredPar's post:

Module Module1
    Sub Main()
        Dim field = GetType(Test).GetField("Field", Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance)
        Dim test = New Test
        Dim GetValue = New Func(Of Test, String)(Function(t As Test) field.GetValue(test))
        'This line indicates a compile error: 'Expression does not produce a value': 
        Dim SetValue = New Action(Of Test, String)(Function(t As Test, value As String) DirectCast(field, Object).SetValue(test, value))
    End Sub
End Module

Notice the cast to object at

Dim SetValue = New Action(Of Test, String)(Function(t As Test, value As String) DirectCast(field, Object).SetValue(test, value))
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top