I'm new to Linq to Objects, and I've just hit the problem of anonymous types and scope.
For example, this works just fine:
Public Sub CreateResults()
results = From e In CustomerList
Join f In OrderList On CustomerList.ID Equals OrderList.开发者_StackOverflow中文版ID
Select New With {e.FirstName, e.LastName, f.OrderID}
For Each r in results
Console.Writeline(r.FirstName, r.LastName, r.OrderID)
Next t
End Sub
This however does not:
Public Class Foo
Private _linqResults
Public Sub CreateResults()
_linqResults = From e In CustomerList
Join f In OrderList On CustomerList.ID Equals OrderList.ID
Select New With {e.FirstName, e.LastName, f.OrderID}
End Sub
Public Sub PrintResults()
For Each r in _linqResults
Console.Writeline(r.FirstName, r.LastName, r.OrderID)
Next t
End Sub
End Class
I've been looking through SO and other places trying to find a simple solution to this without much luck. Is there any way to access the fields of an anonymous type outside the scope of the method containing the Linq query? Something like:
Console.Writeline(r("FirstName").ToString, r("LastName").ToString)
would be acceptable, though not ideal.
I really, really don't want to start creating additional classes/structures/DTOs to handle what are supposed to be dynamic queries.
It is not possible to infer the types the way you want. You have a few choices though:
Make a additional class (which you don't want)
Change the style of the class so CreateResults and PrintResults is in the same method as you have done. BUT you properly have a good reason not to do that.
Use the dynamic type (I guess there is one in VB, but I don't know for sure. I'm a C# man) and then you simple access the properties you want as you do in your example. This is obviously not as fast as static typing.
There is a hack to do it (at least in C#). But it is not pretty. See How to return Anonymous Type while using Linq
Instead of using a custom class you could use the tuple classes. System.Tuple and store the data there. They came in .Net 4 I think.
In the end I really think a custom class is the way to go unless you have a good reason not to. I would also like a way to do the same thing you want to, but a custom class can be described in a few lines with newer syntax.
EDIT: Added a few points and changed a little bit
Example with dynamic in C# as requested
class Foo
{
private dynamic _linqResults;
public void CreateResults()
{
var someData = Enumerable.Range(1, 10);
_linqResults = from i in someData
select new
{
Number = i
};
}
public void PrintResults()
{
foreach (var i in _linqResults)
Console.WriteLine(i.Number);
}
}
As you maybe see, it is almost the same syntax as you want. It just uses dynamic which is a bit slower - but it sounds like that you already uses or will use some kind of dynamic/reflection in datagrid and csv. It of cause depends on which DataGrid and CSV (your own?) you use.
As mentioned in another answer, the compiler can't infer the types and IntelliSense will not be your guide in PrintResults.
Little update VB has a similar syntax which you can find a good walk-trough with here: Link
Here's the deal.
You're creating an anonymous type. The compiler only "knows" about the anonymous type within the scope in which it is created.
In the second example, you are attempting to store that anonymous type outside of the scope of its creation. You can do this, but since the type is anonymous you lose the ability to access the compiler-generated properties except via reflection.
Long story short, if you wish to store the results of a linq query outside of the scope it is created, you must create a type to hold those results.
精彩评论