Ryan
Ryan

Reputation: 1791

Return data type for an AnonymousType#1

What is the correct return data type for an AnonymousType#1?

This code is working.

var c = p.IQueryableGetAll()
         .Where(r => r.Gender == "M")
         .Select(r => new { r.FirstName, r.LastName })
         .ToList();

But when I placed it inside a function, error occurs.

public List<object> GetFirstNameAndLastNameOfMales()
{
   var p = new Program();
   return p.IQueryableGetAll()
           .Where(r => r.Gender == "M")
           .Select(r => new { r.FirstName, r.LastName })
           .ToList();
}

Here's the error

Cannot implicitly convert type System.Collections.Generic.List<AnonymousType#1> to System.Collections.Generic.List<object>

How is it done correctly? Thank you.

Upvotes: 0

Views: 114

Answers (2)

Christos
Christos

Reputation: 53958

You query in both cases is correct. However that causes the problem in the second case is the return type of your method.

You could try this one:

 return p.IQueryableGetAll()
         .Where(r => r.Gender == "M")
         .Select(r => new { r.FirstName, r.LastName }).ToList<Object>();

The reason why you are getting this error is because

Select(r => new { r.FirstName, r.LastName })

select an anonymous type for each element in the sequence that has Gender==M. An the .ToList() at the end of your query creates a List of objects that have as their type this anonymnous type with these two properties.

A better option would be to create a class that will hold these two properties, let's call it Customer and then do the following:

public List<Customer> GetFirstNameAndLastNameOfMales()
{
    var p = new Program();
    return p.IQueryableGetAll()
            .Where(r => r.Gender == "M")
            .Select(r => new Customer { 
                    FirstName = r.FirstName, 
                    LastName = r.LastName
            }).ToList();
}

Upvotes: 2

D Stanley
D Stanley

Reputation: 152626

It doesn't work because List<T> is not covariant - it is a list of a specific type, so you can't add any object to it. You can either:

  1. Create a concrete type and use it
  2. Cast your result to object :

    .Select(r => (object)(new { r.FirstName, r.LastName }))
    
  3. change the return type to IEnumerable<object> which is covariant (since you can't add to it)

Option 1 is the cleanest but requires additional code - options 2 and 3 are easy on the query side but require reflection or dynamic on the client side (and run-time vulnerability, and lack of compile-time safety, etc.).

Upvotes: 0

Related Questions