2014-01-10 120 views
2

在下面的代碼中使用動態類型的優點是什麼?在LINQ中使用動態類型

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

    return queyResult.ToList<dynamic>(); 
} 

什麼時候你會去返回一個列表。

是爲了避免創建只能很少使用的類型?

+1

我個人在這裏的觀點是「不這樣做」。你基本上將C#提供給你的所有好的類型安全性拋棄了,因爲你不想爲系統增加一個類型。在某些情況下,你應該這樣做,但我在這裏沒有看到它。 –

+2

推測性的,但注意到匿名類型不能在方法範圍之外被引用,可能原來的編碼器並沒有像你說的那樣創建一個確定類型(以及不正確地拼寫'query')。我能想到的唯一可能的好處是在調用代碼中存在一些鴨式打印的通用性,其他方法返回具有「Age」和「FirstName」屬性的類型。確實非常危險的東西。 – StuartLC

+1

匿名類型可以使方法/類內部的工作更容易一些。當你想要在外部實體中調用類方法的公共邊界時,應該使用類型來明確它們將返回的值,以迫使調用者深入閱讀實現以找出他們將獲得的內容背部。 – 48klocs

回答

4

如果您正在進行查詢並且只使用了方法中的結果,那麼使用匿名類型非常有用。

在這種情況下,您將返回方法中的數據。從一個方法返回數據時,您希望消費者確切地知道期望什麼(他們顯然沒有使用動態類型)。因此,使用動態類型當然不是一個好主意。

2

一種方法無法返回匿名類型(這是您使用new { employee.FirstName, employee.Age }創建的)。使用dynamic可以繞過這個問題。

我不會推薦以這種方式使用dynamic:要麼返回Employee,要麼創建只有這些屬性的另一個類型。主要原因是dynamic沒有明確告訴那些使用GetEmployees哪些屬性可用。由於它必須在運行時解析屬性名稱,因此它的運行時性能也很小。

2

如果此方法不是公開API的一部分,並且只能由您或您的開發人員使用,則可以使用Tuple類。

​​

然後訪問值如下

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

我不推薦使用它作爲公共API的一部分,因爲它目前尚不清楚哪些項目contais什麼樣的價值。但是,爲了私人使用,這是獲取數據臨時類的好方法。

3

這顯然是dynamic關鍵字的誤用 - 它應該僅用於在編碼時無法定義類型的對象實例(例如與動態語言(如Python)交互的情況)。作者只是懶得定義他可以從方法返回的類型。

取而代之的是,上面的代碼應該改成這樣:

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 queyResult = from employee in source 
         where employee.Age > 20 
         select new Person(employee.FirstName, employee.Age); 

    return queyResult.ToList(); 
} 

關於ToList():以ToList()的調用是有道理的,因爲它「物化」以前的LINQ查詢的結果。否則,查詢將推遲執行,直到實際迭代爲止 - 這在大多數情況下不適用於上述場景(但請注意,您可以在此放棄類型參數,無論如何都由編譯器推斷)。