简体   繁体   中英

Using dynamic types with LINQ

What is the advantage of using dynamic type in the below code?

public static List<dynamic> GetEmployees()
{
    List<Employee> source = GenerateEmployeeCollection();
    var queryResult = from employee in source
                      where employee.Age > 20
                      select new { employee.FirstName, employee.Age };

    return queryResult.ToList<dynamic>();
}

And when would you go for returning a List<dynamic> .

Is to avoid creating types which would be used only very rarely?

Using anonymous types is great if you're making a query and only you are consuming the results in your method.

In this case, you're returning the data from your method. When returning data from a method, you want the consumer to know exactly what to expect (which they obviously don't with a dynamic type). Therefore, using a dynamic type is certainly not a good idea.

This clearly is a misuse of dynamic keyword - it should be used ONLY for object instances for which the type cannot be defined at the time of coding (which is eg the case when interacting with dynamic languages like Python). The author was just too lazy to define a type that he could return from the method.

Instead, the above code should be changed to this:

public class Person
{
    public string FirstName { get; private set; }
    public int Age { get; private set; }

    public Person(string firstName, int age)
    {
        FirstName = firstName;
        Age = age;
    }
}
...
public static List<Person> GetEmployees()
{
    List<Employee> source = GenerateEmployeeCollection();
    var queryResult = from employee in source
                      where employee.Age > 20
                      select new Person(employee.FirstName, employee.Age);

    return queryResult.ToList();
}

Regarding ToList(): The call to ToList() makes sense, since it 'materializes' the result of the previous LINQ query. Otherwise, the query would defer execution until actually iterated - and this is mostly not desirable in such scenarios as above (but note that you can drop the type argument here, it's inferred by the compiler anyway).

A method cannot return an anonymous type (that's what you create with new { employee.FirstName, employee.Age } ). Using dynamic bypasses this problem.

I wouldn't recommend using dynamic in this way: Either return Employee , or create another type with just those properties. The main reason is that dynamic doesn't explicitly tell those using GetEmployees what properties are available. It also has a minor runtime performance hit since it must resolve the property name at runtime.

If this method is not a part of the public API and is used only by you or your fellow developers, you can use the Tuple class for this.

public static List<Tuple<string, int>> GetEmployees()
{
    List<Employee> source = GenerateEmployeeCollection();
    var queryResult = from employee in source
                      where employee.Age > 20
                      select Tuple.Create(employee.FirstName, employee.Age);

    return queryResult.ToList();
}

Then access values as follows

var emps = GetEmployees();
var firstEmpName = emps[0].Item1; // FirstName
var firstEmpage = emps[0].Item2; // Age

I don't recommed to use it as a part of a public API since it's not clear which item contais what value. However, for the private usage sake, it's a nice way to get a temporary class for data.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM