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!
-
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 = ...
Nathan W : why does the second one work fine?Shimmy : donno, it does try and seeJaredPar : @Nathan, I misread the problem and updated my answer.Nathan W : That sounds a bit better +1Shimmy : I prefer to cast it, because I need it in more cases where I use it directly. look at the post.Shimmy : while enjoying from intellisense support around. -
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))
0 comments:
Post a Comment