2008-10-30 53 views

回答

1

嗯,你似乎是out of luck

我用一個問題今天奮力把一些C#到VB.NET時。 C#有一個非常酷的「yield return」語句,用於迭代器模塊爲枚舉器對象提供一個值。 VB.NET沒有「yield」關鍵字。所以,有幾個解決方案(其中沒有一個真的很乾淨)來解決這個問題。你可以使用return語句來返回值,如果你正在循環,想打破一個枚舉器並返回一個值。但是,如果您想要返回整個枚舉,請創建子類型的List()並返回列表。既然你通常在IEnumerable中使用它,那麼List()就可以很好地工作。

這是寫在一年前,不知道是否有人想出了別的從那以後更好

..


編輯:這將在VB.NET的11版本是可能的(在VS2010之後),計劃對迭代器的支持。規格is available here

1

C#的產量關鍵字強制編譯器在後臺,以支持它創建一個狀態機。 VB.Net沒有yield關鍵字。但它確實有一個構造,可以讓你在一個函數中創建一個狀態機:Static function members

應該可以通過創建實現IEnumerable泛型類以及所需要的狀態機,並把實例作爲函數內的靜態成員模仿產量恢復功能的影響。

這,當然需要實現的功能之外的類。但如果做得好,班級應該在一般情況下可重複使用。雖然我沒有提供足夠的想法來提供任何實施細節。

+0

嘿喬爾,你已經提到過這個想法至少兩次了。花哨進一步豐富你的想法? – 2009-01-26 23:12:15

+0

我已經深入瞭解了這一點,並且我不確定是否可以在VB.Net Static局部變量中創建與C#的yield關鍵字相同的狀態機。並不是說這是不可能的,但它肯定不會是微不足道的,最後你還是得寫一些奇怪的代碼分配給機器。即使你不能在Visual Studio 2005中做,因爲它需要lambda表達式。 – 2009-09-23 16:04:07

4

我仍然對這個概念也很感興趣。文章Use Iterators in VB Now最近發佈在Visual Studio Magazine中。

-4

下面給出的輸出:2,4,8,16,32

在VB。NET

Public Shared Function setofNumbers() As Integer() 

    Dim counter As Integer = 0 
    Dim results As New List(Of Integer) 
    Dim result As Integer = 1 
    While counter < 5 
     result = result * 2 
     results.Add(result) 
     counter += 1 
    End While 
    Return results.ToArray() 
End Function 

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 
    For Each i As Integer In setofNumbers() 
     MessageBox.Show(i) 
    Next 
End Sub 

在C#

private void Form1_Load(object sender, EventArgs e) 
{ 
    foreach (int i in setofNumbers()) 
    { 
     MessageBox.Show(i.ToString()); 
    } 
} 

public static IEnumerable<int> setofNumbers() 
{ 
    int counter=0; 
    //List<int> results = new List<int>(); 
    int result=1; 
    while (counter < 5) 
    { 
     result = result * 2; 
     counter += 1; 
     yield return result; 
    } 
} 
0

請記住,LINQ expresssions的延遲執行和懶惰評價的屬性和方法使我們能夠有效地實現自定義的迭代器直到yield語句.NET 4.5可用。 Yield由LINQ表達式和方法在內部使用。

以下代碼演示了這一點。

Private Sub AddOrRemoveUsersFromRoles(procName As String, 
             applicationId As Integer, 
             userNames As String(), 
             rolenames As String()) 
    Dim sqldb As SqlDatabase = CType(db, SqlDatabase) 
    Dim command As DbCommand = sqldb.GetStoredProcCommand(procName) 
    Dim record As New SqlDataRecord({New SqlMetaData("value", SqlDbType.VarChar,200)}) 
    Dim setRecord As Func(Of String, SqlDataRecord) = 
     Function(value As String) 
      record.SetString(0, value) 
      Return record 
     End Function 
    Dim userNameRecords As IEnumerable(Of SqlDataRecord) = userNames.Select(setRecord) 
    Dim roleNameRecords As IEnumerable(Of SqlDataRecord) = rolenames.Select(setRecord) 
    With sqldb 
     .AddInParameter(command, "userNames", SqlDbType.Structured, userNameRecords) 
     .AddInParameter(command, "roleNames", SqlDbType.Structured, roleNameRecords) 
     .AddInParameter(command, "applicationId", DbType.Int32, applicationId) 
     .AddInParameter(command, "currentUserName", DbType.String, GetUpdatingUserName) 
     .ExecuteNonQuery(command) 
    End With 
End Sub