2009-04-22 7 views
2
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 

Dites-moi ce qui ne va pas mais Module2 fonctionne parfaitement!Problème lors de la déclaration d'une méthode anonyme avec vb.net Action (Of T) et lambda

Répondre

5

EDIT Grattez ma réponse originale, j'ai mal interprété le problème.

La raison pour laquelle cela ne compile pas est un problème d'inférence de type et de liaison tardive. Dans le premier exemple de champ est une variable locale et peut donc participer à l'inférence de type. Le compilateur déduira correctement le type à FieldInfo. Cela signifie que l'appel SetValue est un appel statiquement typé. C'est une méthode de retour vide et donc incompatible avec une expression Function lambda qui nécessite une valeur de retour.

La valeur du champ dans le second exemple est cependant déclarée au niveau du module. Ces variables ne sont pas sujettes à l'inférence de type et donc l'objet type sera choisi. Comme le type est object, l'appel SetValue devient un appel lié tardivement. Tous les appels liés tardivement sont supposés pointer vers une fonction qui a un type de retour d'objet. Au moment de l'exécution, si la fonction renvoie void, rien ne sera réellement retourné. Donc, dans ce contexte, il s'agit d'une expression de retour non vide et donc compile. Une option que vous devez contourner est de saisir explicitement le champ en tant qu'objet dans le premier exemple. Cela forcera à être un appel en retard lié et il compilera tout comme le deuxième

Dim field As Object = ... 
+1

Pourquoi le second fonctionne-t-il correctement? –

+0

donno, il fait essayez et voir – Shimmy

+1

@Nathan, j'ai mal interprété le problème et mis à jour ma réponse. – JaredPar

1

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 

Avis du casting à l'objet à

Dim SetValue = New Action(Of Test, String)(Function(t As Test, value As String) DirectCast(field, Object).SetValue(test, value))