2017-06-30 106 views
11

由於C#7引入了值元組,它們是否有比元組更適合的有意義的場景?C#中的C#匿名類型是多餘的7 7

例如,下面的行

collection.Select((x, i) => (x, i)).Where(y => arr[y.i].f(y.x)).ToArray(); 

使得以下行

collection.Select((x, i) => new {x, i}).Where(y => arr[y.i].f(y.x)).ToArray(); 

冗餘。

對於其中一個更好地用於另一個(用於性能原因或優化)的用例是什麼?

很明顯,如果需要超過六個字段,元組不會被使用,但有沒有更多的細微差別呢?

+3

可讀性嗎? 'new {x,i}'完全清楚它是一個正在返回的新對象,而我不得不比較這兩個例子來找出第一個例子。但那可能就是我。 – stybl

+13

首先,它們在表達式樹中支持,而元組文字不是...... –

+7

請注意,您的示例不會在C#7.0中編譯,因爲'(x,i)'具有未命名的元組元素,但它們是隱式地在C#7.1中命名。 –

回答

12

有匿名類型和C#7元組,其可以是或可以不是在某些情況下使一個比另一個更合適之間的各種差異:

  • C#7元組是ValueTuple<>第這意味着它們是值類型而匿名類型是引用類型。
  • 元組允許在編譯時進行靜態類型化,因爲它們是可以明確表達的類型。因此,您可以將它們用作方法參數,返回類型等。
  • 匿名類型的成員是存在於該類型上的實際屬性。元組項目是字段
  • 匿名類型的屬性具有實際名稱,而元組上的字段僅命名爲ItemN(對於數字N)。標籤只是編譯器主要使用的元數據信息,並不會與實際的元組對象一起保存。
  • 因爲創建一個匿名類型實際上在引擎蓋下創建了一個類型,所以您對它們有一個類型安全級別。由於元組只是具有應用類型參數的泛型容器,因此對它們沒有完整的類型安全性。例如,對於大小(int, int)元組將完全兼容(int, int)元組,位置,而匿名類型完全關閉。
  • 正如Jon Skeet所述,表達式樹中的C#7元組語法爲currently not supported
+0

好的答案。你會不會包含Jon Skeet關於元組文字不適用於表達式樹的觀點? –

+0

我喜歡這個答案,因爲它提供了有關'ValueTuple's的實現細節。但它仍然沒有回答OP問題:匿名類型比「ValueTuple」好嗎?第5點(據我所知)更多的是考慮使用普通類型而不是「ValueTuple」。 –

+0

@VadimOvchinnikov是的,當然有場景。這兩種功能之間的區別是相關的。 - 如果您需要示例,請使用[Dapper](https://github.com/StackExchange/Dapper),您可以在其中傳入帶有* named *查詢參數的匿名類型。由於元組對象沒有關聯的名稱,因此無法對它們進行此操作。 – poke

1

@poke當前的答案是正確的,並注意到元組和匿名類型之間的差異。我要討論爲什麼你仍然會使用它們或者比較喜歡它們。

有兩個新的c#7功能可以退出匿名類型。 ValueTuplesRecords

,你會不會使用匿名類型的主要原因是

  • 你不能在全球範圍使用匿名類型和在本地使用時纔會類型安全的。不是地方,你必須把它作爲具有顯著的性能開銷,你喜歡過的元組匿名類型

原因dynamic對象。

  • 他們是在所有地方類型安全。 (不管命名)

  • 它們可以用作方法參數,類型參數,字段和幾乎每一處。 (是的,我說了很多,有些地方需要採用元組,這是它的時間問題。)

  • 因爲它們可以用作類型參數,所以您可能更喜歡將單個參數中的輕量級參數組包裝起來。像Stack<(min, mid, max)>

  • 您可以更改項目命名時,你永遠覺得它的相應的,在一般情況下名字item可滿足在更具體的情況下,你需要更具體的名字太像car

  • 他們是隱式轉換, int, int可以分配給(int, long)而不需要顯式轉換。

  • 它們用於Deconstruct s。這給語言帶來了很多語法糖。

  • 你可以有多個任務和聲明一樣(int x, int y) = (0, 1)

具有所有這個功能,還有一個原因,你可能更喜歡匿名型過元組。

  • 匿名類型是引用類型,但元組是值類型。

但是如果你想在全局使用匿名類型呢?你喜歡有動態對象還是靜態類型的對象?

傳入記錄功能再次擊敗匿名類型。通過記錄,您可以簡短,簡潔,方便地定義班級。沒什麼大不了的。只是一條線

public class Point(X, Y); 

類型安全到處都是,你也有參考類型在手。這兩個新功能帶來的每一件事都擊敗了匿名類型。

請注意,記錄尚未添加,我們只需等待。

僅存匿名類型的實際使用會

  • 他們仍然作爲向後兼容的功能,當你在本地使用匿名類型

  • 他們可以Linq中使用的查詢。因此我不會說匿名類型是多餘的。

正如我所說ValueTuples與每個組件都不兼容。它只是時間的問題,但未來它將如何。

足夠的論據。在我的小見解中,匿名類型的使用變得很少見,舊程序員可能仍然習慣於在Linq中使用匿名類型。