2015-10-01 101 views
2

我正在使用VB.Net來分配一個委託。但是我不想定義一個方法(子)/函數。「單行語句lambdas必須包含一個語句。」爲什麼這個錯誤?

簡單地給Nothing不起作用,因爲DelegateCommand會拋出運行時異常,如果Nothing在Delegate中設置。

那麼,爲什麼我會得到這個錯誤?

"Single Line statements lambdas must include exactly one statement."

下面是代碼

Public Delegate Function DelegateCommand(Of T)(ByVal arg As T) As Boolean 

Private _foobar As DelegateCommand(Of Object) 
Public ReadOnly Property FooBar() As DelegateCommand(Of Object) 
    Get 
     If _foobar Is Nothing Then 
      _foobar = New DelegateCommand(Of Object)(Sub(), AddressOf OnFooBarCommandExecuted) 
     End If 
     Return _foobar 
    End Get 
End Property 

Private Function OnFooBarCommandExecuted(ByVal parameter As Object) As Boolean 
    Return False 
End Function 

這裏是圖像

+14

難道你不能創建一個不敏感的代碼副本,並顯示它*爲文本*?或者更好的是,創建一個[Minimal,Complete,and Verifiable Example](http://stackoverflow.com/help/mcve)並向我們展示。 –

+1

http://stackoverflow.com/questions/5036549/vb-net-statement-lambdas-cannot-be-converted-to-expression-trees-compile-tim – CodeCaster

+0

@JoachimPileborg:完成。 –

回答

4

的VB.NET編譯器團隊不得不爲lambda表達式到語言的麻煩裏上演的支持相當數量。在舊的舊的語言(如Basic)中絕對不容易做到。如果生成「最佳」診斷結果非常困難,那麼語言解析器首先必須通過帶有參數的函數()與沒有參數的Sub()進行匹配。不能這樣做,它不會知道要作爲函數參數值傳遞什麼。更糟的是,它需要生成MSIL代碼來清理堆棧並彈出函數返回值,但是你的Sub()表示沒有代碼。這種差異讓它大叫Eeek!一個糟糕的診斷和放棄。

在它發現代碼中存在更根本錯誤之前,它會嘗試將兩個方法傳遞給委託構造函數。你應該知道的更大的問題,遺憾的是沒有報告,因爲它放棄了第一個錯誤。

Roslyn項目值得注意,語言解析器被完全重寫,併爲此代碼生成更好的診斷。集成到VS2015,你現在得到:

錯誤BC32008:委託「ConsoleApplication1.Example.DelegateCommand(的對象)」需要「AddressOf」表達式或lambda表達式作爲唯一的參數傳遞給它的構造。

這會讓你在某處,注意作爲錯誤消息中唯一的參數。兩種方法可以在錯誤消息中暗示。一個有效的「AddressOf`表達式作爲唯一的參數:

_foobar = New DelegateCommand(Of Object)(AddressOf OnFooBarCommandExecuted) 

或者lambda表達式作爲唯一的參數:

_foobar = New DelegateCommand(Of Object)(Function(parameter) 
               Return False 
              End Function) 

由於不再需要編寫OnFooBarCommandExecuted()函數,你想要什麼去完成。 VB.NET提供了大量的語法糖來進一步簡化代碼。即使委託聲明瞭一個,你也可以聲明lambda表達式不帶任何參數。而且您不必顯式編寫委託構造代碼,編譯器可以從_foobar變量中推斷出它。其中代碼摺疊爲:

_foobar = Function() False 
+0

OP沒有回答我的評論/問題,但因爲你顯然發現了一個被廣泛接受的答案......你不覺得OP意圖是從'FooBar調用'CanExecute'會返回'False',調用'Execute'將不起作用?如果答案是肯定的,你的答案如何解決? – Amit

+0

(順便說一句,我非常肯定你對問題本身的編輯導致你這個答案,並且它是錯誤的。你定義了一個新的Delegate而不是使用[DelegateCommand](https://msdn.microsoft.com/en -us /庫/ gg431410(v = pandp.40)。aspx)OP的意圖 - 請參閱Sarvesh的回答評論) – Amit

+0

我沒有定義一個新的代表,聲明從這個問題中缺失。所以我提供了一個。如有必要,OP可以糾正它,我懷疑這是必要的。 –

1

你需要改變一些代碼 在屬性的getter,使用此一行代碼

_foobar = New DelegateCommand(Of Object)(Sub() 
             End Sub, AddressOf OnFooBarCommandExecuted) 

一行lambda必須只有一條語句,所以Sub()是一行lambda,它期望一條語句。如果你的方法沒有聲明,那麼你不能使用單行lambda。

零聲明中λ爲

Dim zeroStatementLambda = Sub() 
          End Sub 

,它似乎是情況下,你可以使用單一的參數DelegateCommand構造

_foobar = New DelegateCommand(Of Object)(AddressOf OnFooBarCommandExecuted) 

變化OnFooBarCommandExecuted

Private Function OnFooBarCommandExecuted() As Func(Of Object, Boolean) 
    Return Function(parameter As Object, Boolean) 
       Return False 
      End Function 
End Function 
+0

DelegateCommand類有兩個構造函數。你在引用一個參數。我的問題是關於需要兩個參數的問題。 –

+0

@NikhilAgrawal編輯 –

+0

@amit:我知道解決方案,以及如何糾正這個問題,但想知道背後的場景,我猜Hans Passant適合。 –

1
定義

如果您只想傳遞AddressOf之前刪除Sub() Ë委託DelagateCommand構造,這樣

Public ReadOnly Property FooBar() As DelegateCommand(Of Object) 
    Get 
     If _foobar Is Nothing Then 
      _foobar = New DelegateCommand(Of Object)(AddressOf OnFooBarCommandExecuted) 
     End If 
     Return _foobar 
    End Get 
End Property 

您可以指定一個代表或者匿名與子()...語句,或用AddressOf運算符,你通過現有的函數的名稱,而不是兩個。

但我想你實際上是想通過兩個代表到你的DelegateCommand。首先執行的命令,第二個命令可以執行的Func返回。 在這種情況下,您需要向第一個參數添加一些語句。 這樣,

Public ReadOnly Property FooBar() As DelegateCommand(Of Object) 
    Get 
     If _foobar Is Nothing Then 
      _foobar = New DelegateCommand(Of Object)(Sub() 
                'statement here 
                End Sub, AddressOf OnFooBarCommandExecuted) 
     End If 
     Return _foobar 
    End Get 
End Property 
相關問題