Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
La scelta del tipo appropriato comporta la considerazione dell'usabilità, delle prestazioni e dei compromessi rispetto ad altri tipi. I tipi anonimi sono disponibili a partire da C# 3.0, mentre i tipi generici System.Tuple<T1,T2> sono stati introdotti con .NET Framework 4.0. Da allora sono state introdotte nuove opzioni con il supporto a livello di linguaggio, come System.ValueTuple<T1,T2>, che, come suggerisce il nome, forniscono un tipo di valore con la flessibilità dei tipi anonimi. In questo articolo si apprenderà quando è opportuno scegliere un tipo rispetto all'altro.
Usabilità e funzionalità
I tipi anonimi sono stati introdotti in C# 3.0 con espressioni LINQ (Language-Integrated Query). Con LINQ, gli sviluppatori spesso proiettano i risultati delle query in tipi anonimi che contengono alcune proprietà selezionate dagli oggetti in uso. Si consideri il seguente esempio, che istanzia una matrice di oggetti DateTime e ne itera proiettandoli in un tipo anonimo con due proprietà.
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}");
}
I tipi anonimi vengono create tramite l'operatore new
e i nomi e i tipi di proprietà vengono dedotti dalla dichiarazione. Se due o più inizializzatori di oggetti anonimi nello stesso assembly specificano una sequenza di proprietà nello stesso ordine e con gli stessi nomi e tipi, il compilatore considera gli oggetti come istanze dello stesso tipo. Condividono le stesse informazioni sul tipo generate dal compilatore.
Il frammento di codice C# precedente proietta un tipo anonimo con due proprietà, in modo analogo alla classe C# generata dal compilatore seguente:
internal sealed class f__AnonymousType0
{
public string Formatted { get; }
public long Ticks { get; }
public f__AnonymousType0(string formatted, long ticks)
{
Formatted = formatted;
Ticks = ticks;
}
}
Per altre informazioni, vedere Tipi anonimi. La stessa funzionalità esiste con le tuple durante la proiezione nelle query LINQ, ed è possibile selezionare le proprietà nelle tuple. Queste tuple passano attraverso la query, esattamente come i tipi anonimi. Si consideri ora l'esempio seguente usando .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}");
}
Con , l'istanza System.Tuple<T1,T2>espone le proprietà degli elementi numerati, ad esempio Item1
, e Item2
. Questi nomi di proprietà possono rendere più difficile comprendere la finalità dei valori delle proprietà, poiché il nome della proprietà fornisce solo un valore ordinale. Inoltre, i System.Tuple
tipi sono tipi di riferimento class
. Tuttavia System.ValueTuple<T1,T2> , è un tipo di valore struct
. Il frammento di codice C# seguente usa ValueTuple<string, long>
per proiettare in . In questo modo, assegna l'uso di una sintassi letterale.
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}");
}
Per altre informazioni sulle tuple, vedere Tipi di tupla (Riferimenti per C#) o Tuple (Visual Basic).For more information about tuples, see Tuple types (C# reference) or Tuples (Visual Basic).
Gli esempi precedenti sono tutti equivalenti a livello funzionale, ma esistono lievi differenze nell'usabilità e nelle implementazioni sottostanti.
Svantaggi
Potresti voler usare sempre ValueTuple al posto di Tuple e i tipi anonimi, ma ci sono dei compromessi che dovresti considerare. I ValueTuple tipi sono modificabili, mentre Tuple sono di sola lettura. I tipi anonimi possono essere usati negli alberi delle espressioni, mentre le tuple non possono. La tabella seguente offre una panoramica di alcune delle principali differenze.
Differenze principali
Nome | Modificatore di accesso | TIPO | Nome membro personalizzato | Supporto alla decostruzione | Supporto dell'albero delle espressioni |
---|---|---|---|---|---|
Tipi anonimi | internal |
class |
✔️ | ❌ | ✔️ |
Tuple | public |
class |
❌ | ❌ | ✔️ |
ValueTuple | public |
struct |
✔️ | ✔️ | ❌ |
Serializzazione
Una considerazione importante quando si sceglie un tipo è se deve essere serializzata o meno. La serializzazione è il processo di conversione dello stato di un oggetto in un formato che può essere salvato in modo permanente o trasportato. Per altre informazioni, vedere Serializzazione. Quando la serializzazione è importante, la creazione di un class
o struct
è preferibile rispetto a tipi anonimi o tipo tupla.
Prestazioni
Le prestazioni tra questi tipi dipendono dallo scenario. L'impatto principale comporta il compromesso tra allocazioni e copia. Nella maggior parte degli scenari, l'impatto è ridotto. Quando possono verificarsi gravi impatti, è necessario prendere misure per informare la decisione.
Conclusione
In qualità di sviluppatore che sceglie tra tuple e tipi anonimi, esistono diversi fattori da considerare. In generale, se non si lavora con gli alberi delle espressioni e si ha familiarità con la sintassi delle tuple, allora scegli ValueTuple, poiché fornisce un tipo valore con la flessibilità di nominare le proprietà. Se lavorate con alberi delle espressioni e preferite denominare le proprietà, scegliete tipi anonimi. In caso contrario, usare Tuple.