Választás a névtelen és a rekordtípusok között
A megfelelő típus kiválasztásához figyelembe kell venni a használhatóságot, a teljesítményt és a kompromisszumokat a többi típushoz képest. A névtelen típusok a C# 3.0 óta érhetők el, míg az általános System.Tuple<T1,T2> típusokat a .NET-keretrendszer 4.0-val vezették be. Azóta új lehetőségeket vezetnek be a nyelvi szintű támogatással, például System.ValueTuple<T1,T2> - ami a névből is következik, egy értéktípust biztosít a névtelen típusok rugalmasságával. Ebből a cikkből megtudhatja, hogy mikor érdemes egy típust választani a másikhoz.
Használhatóság és funkcionalitás
A névtelen típusok a C# 3.0-ban jelentek meg a Language-Integrated Query (LINQ) kifejezésekkel. A LINQ használatával a fejlesztők gyakran névtelen típusokká fejlesztik a lekérdezések eredményeit, amelyek a használt objektumok néhány kiválasztott tulajdonságát tárolják. Vegyük az alábbi példát, amely egy objektumtömböt DateTime példányosít, és végigfuttat rajtuk, és egy névtelen típusba vetíti két tulajdonsággal.
var dates = new[]
{
DateTime.UtcNow.AddHours(-1),
DateTime.UtcNow,
DateTime.UtcNow.AddHours(1),
};
foreach (var anonymous in
dates.Select(
date => new { Formatted = $"{date:MMM dd, yyyy hh:mm zzz}", date.Ticks }))
{
Console.WriteLine($"Ticks: {anonymous.Ticks}, formatted: {anonymous.Formatted}");
}
A névtelen típusok példányosítása az new
operátor használatával történik, és a tulajdonságnevek és -típusok a deklarációból következtetnek. Ha két vagy több névtelen objektum inicializálója ugyanabban a szerelvényben olyan tulajdonságok sorozatát adja meg, amelyek azonos sorrendben vannak, és azonos nevűek és típusok, a fordító az objektumokat azonos típusú példányokként kezeli. Ugyanazokkal a fordító által generált típusinformációkat osztják meg.
Az előző C#-kódrészlet egy névtelen típust tervez két tulajdonsággal, hasonlóan a következő fordító által létrehozott C# osztályhoz:
internal sealed class f__AnonymousType0
{
public string Formatted { get; }
public long Ticks { get; }
public f__AnonymousType0(string formatted, long ticks)
{
Formatted = formatted;
Ticks = ticks;
}
}
További információkért lásd a névtelen típusokat. Ugyanez a funkció létezik a linq-lekérdezésekbe való kivetítéskor a uplokkal is, a tulajdonságokat a csuplok között választhatja ki. Ezek a típusok ugyanúgy haladnak végig a lekérdezésen, mint a névtelen típusok. Most vegye figyelembe a következő példát a System.Tuple<string, long>
.
var dates = new[]
{
DateTime.UtcNow.AddHours(-1),
DateTime.UtcNow,
DateTime.UtcNow.AddHours(1),
};
foreach (var tuple in
dates.Select(
date => new Tuple<string, long>($"{date:MMM dd, yyyy hh:mm zzz}", date.Ticks)))
{
Console.WriteLine($"Ticks: {tuple.Item2}, formatted: {tuple.Item1}");
}
A példány számozott System.Tuple<T1,T2>elemtulajdonságokat tesz elérhetővé, például Item1
: és Item2
. Ezek a tulajdonságnevek megnehezíthetik a tulajdonságértékek szándékának megértését, mivel a tulajdonságnév csak a sorszámot adja meg. Ezenkívül a System.Tuple
típusok referenciatípusok class
. Ez System.ValueTuple<T1,T2> azonban egy értéktípus struct
. A következő C#-kódrészletet használja ValueTuple<string, long>
a projektbe. Ennek során konstans szintaxissal rendeli hozzá.
var dates = new[]
{
DateTime.UtcNow.AddHours(-1),
DateTime.UtcNow,
DateTime.UtcNow.AddHours(1),
};
foreach (var (formatted, ticks) in
dates.Select(
date => (Formatted: $"{date:MMM dd, yyyy at hh:mm zzz}", date.Ticks)))
{
Console.WriteLine($"Ticks: {ticks}, formatted: {formatted}");
}
A rekordokról további információt a Tuple-típusok (C#-referencia) vagy a Tuples (Visual Basic) című témakörben talál.
Az előző példák funkcionálisan egyenértékűek, azonban a használhatóságuk és a mögöttes implementációik között kisebb különbségek vannak.
Kompromisszumok
Érdemes lehet mindig a név nélküli típusokat használni ValueTupleTuple, de érdemes megfontolni a kompromisszumokat. A ValueTuple típusok nem módosíthatók, míg Tuple írásvédettek. A névtelen típusok használhatók a kifejezésfákban, míg a csonkok nem. Az alábbi táblázat áttekintést nyújt a főbb különbségekről.
Fő eltérések
Név | Hozzáférés-módosító | Típus | Egyéni tag neve | Deconstruction support | Kifejezésfa támogatása |
---|---|---|---|---|---|
Névtelen típusok | internal |
class |
✔️ | ❌ | ✔️ |
Tuple | public |
class |
❌ | ❌ | ✔️ |
ValueTuple | public |
struct |
✔️ | ✔️ | ❌ |
Szerializációs
Egy típus kiválasztásakor fontos szempont, hogy szerializálni kell-e. A szerializálás az objektum állapotának megőrzésére vagy átvitelére használható űrlaptá alakításának folyamata. További információ: szerializálás. Ha fontos a szerializálás, hozzon létre vagy class
struct
előnyben részesítse a névtelen típusok vagy a tuple típusok helyett.
Teljesítmény
Az ilyen típusok teljesítménye a forgatókönyvtől függ. A fő hatás magában foglalja a kiosztások és a másolás közötti kompromisszumot. A legtöbb forgatókönyvben a hatás kicsi. Ha jelentős hatások léphetnek fel, méréseket kell tenni a döntés tájékoztatása érdekében.
Összegzés
Fejlesztőként a tuples és a névtelen típusok közötti választáshoz több tényezőt is figyelembe kell venni. Általánosságban elmondható, hogy ha nem a kifejezésfákkal dolgozik, és kényelmesen használhatja a tuple szintaxist, akkor válassza kiValueTuple, hogy milyen értéktípust biztosítanak a tulajdonságok elnevezéséhez. Ha kifejezésfákkal dolgozik, és a tulajdonságokat inkább el szeretné nevezni, válasszon névtelen típusokat. Ellenkező esetben használja a következőt Tuple: .