From Loops to LINQ: Cleaning Up VB.NET Order Filtering with Declarative Queries
Replace verbose loops with LINQ to Objects for cleaner VB.NET order filtering. See a practical example filtering high-priority orders with deferred execution warnings.
12 Nov 2025, 04:49 UTC

The Verbose Loop Problem
When filtering a list of orders in VB.NET, developers often fall back to nested loops with scattered If statements. This creates code that's hard to follow and easy to break when requirements change. For example, pulling all orders over $100 from a specific customer typically means multiple loops, temporary lists, and manual iteration logic.
Enter LINQ to Objects
LINQ to Objects lets you express the same logic as a single, readable query. The query is compiled, type-safe, and executes against in-memory collections without any external dependencies. Here's the core syntax:
Dim highValueOrders = From order In orders
Where order.Total > 100
Select order
Practical Example: Filtering and Projecting Orders
Let's walk through a complete example. Suppose we have an Order class and need to find all high-priority orders from the last 30 days:
Class Order
Public Property OrderId As Integer
Public Property CustomerName As String
Public Property Total As Decimal
Public Property Priority As Integer
Public Property OrderDate As DateTime
End Class
Dim orders As New List(Of Order) From {
New Order With {.OrderId = 1, .CustomerName = "Acme Corp", .Total = 150.0D, .Priority = 2, .OrderDate = DateTime.Now.AddDays(-5)},
New Order With {.OrderId = 2, .CustomerName = "Beta LLC", .Total = 75.0D, .Priority = 1, .OrderDate = DateTime.Now.AddDays(-10)},
New Order With {.OrderId = 3, .CustomerName = "Gamma Inc", .Total = 200.0D, .Priority = 3, .OrderDate = DateTime.Now.AddDays(-2)}
}
Dim recentHighPriority = From o In orders
Where o.Priority >= 2 AndAlso o.OrderDate >= DateTime.Now.AddDays(-30)
Order By o.Total Descending
Select New With {o.OrderId, o.CustomerName, o.Total}
For Each order In recentHighPriority
Console.WriteLine("{0}: {1} - {2}", order.OrderId, order.CustomerName, order.Total)
Next
This query filters by priority and date, sorts by total in descending order, and projects only the fields we need. No temporary collections or manual sorting required. You can paste this into a Console Application in Visual Studio 2022 and run it to see the matching orders printed.
Deferred Execution: A Hidden Gotcha
One critical detail: LINQ queries use deferred execution. The query doesn't run when you declare it—it runs when you enumerate it. This means modifying the source collection after defining the query can produce unexpected results:
Dim query = From o In orders Where o.Total > 100 Select o
orders.Add(New Order With {.Total = 150}) ' Added after the query is defined
Dim results = query.ToList() ' The new order IS included, because the query runs here
If you need a stable snapshot, call .ToList() or .ToArray() immediately after defining the query. A related trap: if a lambda inside the query throws (say, a division by zero), the exception surfaces only during enumeration, not where the query was written, which can make the root cause harder to trace.
When to Reach for Traditional Loops
While LINQ improves readability, it has trade-offs. Complex business logic with side effects doesn't belong in query clauses—keep those in traditional loops where flow control is explicit and debuggable. Also, for very large collections (millions of items), a hand-written loop may outperform LINQ due to delegate invocation and repeated enumeration overhead. If this matters in your scenario, wrap both approaches in a Stopwatch over a representative dataset and compare before committing.
Actionable Takeaway
Replace multi-line filtering loops with LINQ queries for cleaner, more maintainable code. Start by converting simple For Each + If blocks into From...Where...Select statements. Materialize results with .ToList() if you'll reuse the filtered data or if the source collection might change, keep query clauses side-effect free, and profile performance on large datasets to ensure LINQ's convenience doesn't become a bottleneck.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.