Problème déclarant une méthode anonyme avec Action vb.net (Of T) et lambda
-
13-09-2019 - |
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 ce qui est mal, mais Module2 fonctionne tout simplement génial!
La solution
EDIT Grattez ma première réponse, j'ai mal lu le problème.
La raison pour laquelle cela ne compile pas est une question de l'inférence de type et la liaison tardive. Dans le premier champ exemple est une variable locale et peut donc participer à l'inférence de type. Le compilateur correctement déduit du type à FieldInfo. Cela signifie que l'appel SetValue est un appel statiquement typé. Il est une méthode de retour de vide et est donc incompatible avec une expression lambda fonction qui nécessite une valeur de retour.
La valeur du champ dans le deuxième exemple est déclarée mais à un niveau de module. Ces variables ne sont pas soumis à l'inférence de type et par conséquent l'objet de type sera choisi. Étant donné que le type est objet, l'appel SetValue devient un appel en retard lié. Tous les appels en retard liés sont supposés pointer vers une fonction qui a un type de retour de l'objet. Lors de l'exécution si la fonction retourne vide, rien ne sera effectivement retourné. Donc, dans ce contexte, il est une expression renvoie une valeur non vide et compile donc.
L'une des options que vous avez à contourner est de taper explicitement champ comme objet dans le premier exemple. Cela forcera à être un appel en retard lié et il compilera tout comme le second
Dim field As Object = ...
Autres conseils
est bien ici la réponse finale basée sur le post de JaredPar:
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
Remarquez la distribution à l'objet à
Dim SetValue = New Action(Of Test, String)(Function(t As Test, value As String) DirectCast(field, Object).SetValue(test, value))