Làm cách nào để triển khai mẫu lặp trong VB.NET, không có từ khóa yield
?Mẫu Iterator trong VB.NET (C# sẽ sử dụng năng suất!)
Trả lời
Điều này hiện được hỗ trợ trong VS 2010 SP1, với Async CTP, xem: Iterators (C# and Visual Basic) on MSDN và download Visual Studio Async CTP (Version 3).
Mã như thế này, hoạt động:
Private Iterator Function SomeNumbers() As IEnumerable
' Use multiple yield statements.
Yield 3
Yield 5
Yield 8
End Function
Hmm, có vẻ như bạn có thể out of luck:
tôi đã phải vật lộn với một vấn đề ngày nay khi chuyển đổi một số C# để VB.NET. C# có câu lệnh "return return" thực sự thú vị được sử dụng trong một khối lặp để cung cấp một giá trị cho đối tượng điều tra viên. VB.NET không có từ khóa "lợi nhuận". Vì vậy, có một vài giải pháp (không ai trong số đó là thực sự sạch sẽ) để có được xung quanh này. Bạn có thể sử dụng một câu lệnh return để trả về giá trị nếu bạn đang lặp qua và muốn phá vỡ một điều tra viên và trả về một giá trị duy nhất. Tuy nhiên, nếu bạn muốn trả lại toàn bộ liệt kê, hãy tạo Danh sách() của loại con và trả về danh sách. Vì bạn thường sử dụng nó với một IEnumerable, List() sẽ làm việc tốt đẹp.
đó đã được viết cách đây một năm, không chắc chắn nếu có ai đã đưa ra bất cứ điều gì khác tốt hơn kể từ đó ..
Edit: đây sẽ là nơi cư trú của phiên bản 11 của VB.NET (cái sau VS2010), hỗ trợ cho vòng lặp được lên kế hoạch. Thông số kỹ thuật is available here.
VB.NET không hỗ trợ tạo các trình vòng lặp tùy chỉnh và do đó không tương đương với từ khóa lợi nhuận C#. Tuy nhiên, bạn có thể muốn xem bài viết KB How to make a Visual Basic .NET or Visual Basic 2005 class usable in a For Each statement để biết thêm thông tin.
Từ khóa lợi nhuận của C# buộc trình biên dịch tạo ra một máy trạng thái ở chế độ nền để hỗ trợ nó. VB.Net không có từ khóa lợi nhuận. Nhưng nó có một cấu trúc cho phép bạn tạo một máy trạng thái trong một hàm: Static function members. Có thể bắt chước các tác động của hàm trả về lợi nhuận bằng cách tạo ra một lớp chung thực hiện IEnumerable cũng như máy trạng thái cần thiết và đặt một thể hiện như là một thành phần tĩnh bên trong hàm của bạn.
Điều này, tất nhiên, yêu cầu triển khai lớp bên ngoài chức năng. Nhưng nếu được thực hiện đúng thì lớp học nên được tái sử dụng trong trường hợp chung. Tuy nhiên, tôi chưa từng chơi đủ ý tưởng để cung cấp bất kỳ chi tiết triển khai nào.
Tôi vẫn đang quan tâm đến khái niệm này. Bài viết Use Iterators in VB Now gần đây đã được xuất bản trong Tạp chí Visual Studio.
Liên kết bị hỏng! – Peter
Dưới đây cung cấp cho đầu ra: 2, 4, 8, 16, 32
Trong 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
Trong 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;
}
}
Hãy ghi nhớ rằng thực hiện chậm và lười biếng đánh giá tính chất của LINQ expresssions và phương pháp cho phép chúng tôi thực hiện một cách hiệu quả lặp tùy chỉnh cho đến khi báo cáo kết quả sản lượng có sẵn trong .NET 4.5. Năng suất được sử dụng nội bộ bởi các biểu thức và phương thức LINQ.
Mã sau đây minh họa điều này.
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
Hey Joel, bạn đã đề cập ý tưởng này ít nhất hai lần ngay bây giờ. Fancy đưa ra ý tưởng của bạn hơn nữa? –
Tôi đã xem xét điều này sâu hơn một chút, và tôi không còn chắc chắn bạn có thể tạo ra cùng một loại máy nhà nước như từ khóa năng suất của C# trong một biến cục bộ VB.Net tĩnh. Không phải là nó sẽ là không thể, nhưng nó chắc chắn sẽ không phải là tầm thường và cuối cùng bạn vẫn phải viết một số mã kỳ lạ được gán cho máy. Ngay cả khi bạn không thể làm trong visual studio 2005, vì nó sẽ yêu cầu các biểu thức lambda. –