How to declare List<> var for an anonymous type?

Using latest Elements/Data Abstract/VS2019…

I need to declare a List type variable to hold an anonymous type which would be the result of a DALINQ query ending with a ‘select new class()’ . How should I declare this prior to the query? I cant inline declare it since I have to use an If/then/else so that I can run the query two ways based on user input.

List? List? Neither seems to compile properly.

You don’t.

an anonymous type is called like that for a reason — it has no name, and thus you cannot refers to by a name anywhere — this includes four parameters, return values or, indeed, generic arguments.

You can to, say ToList() on a (DA)LINQ result to get a List<your type>, but just like the original type or sequence, you can only use it, or let type inference declare a variable to hold it — you cannot refer to the List type by name.

If thats no an option, you have to declare a concrete type manually and use that instead of the anonymous one, in Select.

hmm, I guess that makes sense. So if I have a select clause like this (plus there are more fields…)

                select new class (AdNumber := arec.AdNumber,
                                  EntryYear := arec.EntryYear,
                                  ReconID := arec.ReconID,
                                  BillNum := arec.ApplyToBill,
                                  PayType := brec.PaymentType,
                                  IsReconciled := arec.IsReconciled,
                                  InvoiceNumber := arec.InvoiceNumber,
                                  InvoiceDate := arec.InvoiceDate,

I should declare a class that matches those field names exactly and everything would work?

best option I’m afraid, yeah. luckily, with Extended Constructir syntax, all you need is a class with properties of the right name, and then

select new YouClass(AdNumber := arec.AdNumber,
                                  EntryYear := arec.EntryYear,
                                  ReconID := arec.ReconID,
                                  BillNum := arec.ApplyToBill,
                                  PayType := brec.PaymentType,
                                  IsReconciled := arec.IsReconciled,
                                  InvoiceNumber := arec.InvoiceNumber,
                                  InvoiceDate := arec.InvoiceDate,

will just compile.

Update: Anton has a better idea he’ll be providing in a bit.

There is another option.

Let’s assume there is a task to load some data using DA LINQ into an anonymous class. The catch is that the where part of the data query might differ based on some user input. Different fields can be used there, one or more conditions can be omitted etc.

It is not possible to predefine a variable for the query result because the result type is anonymous and thus cannot be referenced in code.

Also there is no way to conditionally define different conditions in the where part of the query itself.

he solution is to decompose the LINQ query.
In .NET any LINQ query is actually a chain of method calls hidden behind a fancy syntax. It is possible to write any LINQ query using these method calls only. There is no performance hit as this is actually exactly the same code

So take a look at this code:

method LoadData(foo: Boolean);
begin
  // Define the data source (in this case - remote data table accessed via DA LINQ)
  var query := fDataModule.DataAdapter.GetTable<Customers>().AsQueryable();

  // Add different conditions based on method parameter
  if foo then begin
    query := query.Where(c -> c.Name.StartsWith('A'));
  end
  else begin
    query := query.Where(c -> c.Discount > 0);
  end;

  // Put the data into an anonymous class
  var query1 := query.Select(c -> new class(ID := c.Id, ADDR := c.Address));

  // Load data
  var data := query1.ToList();

  // Debug output
  System.Windows.Forms.MessageBox.Show('Data type: ' + data.GetType().ToString() + #13#10 + 'Data count: ' + data.Count.ToString());
end;

Using this approach it is possible to add different conditions to the query at runtime.

Good idea, yeah! I didn’t think of that.

Thanks Anton!

1 Like