Dicembre 2015

Volume 30 numero 13

Il presente articolo è stato tradotto automaticamente.

Essential .NET - Progettazione di C# 7

Da Mark Michaelis | Dicembre 2015

Mark MichaelisNel momento in che questo articolo, il team di progettazione di c# 7 verrà hanno discusso, pianificazione, la sperimentazione e programmazione per circa un anno. In questo articolo, sarà esempio alcune delle idee che aver esplorato.

Esame, tenere presenti in questo momento sono ancora idee per gli elementi da includere in C# 7. Alcune delle idee il team ha semplicemente parlato, mentre altri hanno reso per quanto riguarda le implementazioni sperimentale. In ogni caso, viene impostato alcuno dei concetti; molti potrebbe non vedere mai la luce; e anche quelli che sono in futuro potrebbero essere visualizzati nelle fasi finali della finalizzazione del linguaggio.

Dichiarazione di tipi di riferimento Non ammettono valori null e Nullable

Probabilmente alcune delle idee predominante nella discussione C# 7 sono quelle relative all'utilizzo di valori null ulteriore miglioramento, allo stesso modo dell'operatore null-condizionale di c# 6.0. Uno dei miglioramenti più semplici potrebbe essere compilatore o verifica di analizzatore che accede a un'istanza del tipo che ammette valori null potrebbe avere come prefisso verifica che il tipo, non è in effetti, null.

In casi quando non è auspicabile per un tipo di riferimento null, se è possibile evitare completamente null? L'idea, è possibile dichiarare l'intento che un tipo di riferimento sarebbe ammette valori null (stringa)? o evitare null (string!). In teoria, potrebbe anche essere possibile presupporre che siano tutte le dichiarazioni di tipo riferimento nel nuovo codice, per impostazione predefinita, non ammette valori null. Tuttavia, come esposto dal mio "essenziale c# 6.0" libro coautore, Eric Lippert, garantendo un tipo di riferimento non sarebbe null in fase di compilazione è estremamente difficile (bit.ly/1Rd5ekS). Anche in questo caso, ciò che sarebbe possibile consiste nell'identificare gli scenari in cui un tipo potrebbe potenzialmente essere null ed essere ancora dereferenziato senza verificare che non si tratta. In alternativa, gli scenari in cui un tipo può essere assegnato il valore null nonostante lo scopo dichiarato che non sia null.

Per ulteriori vantaggi, il team è illustrare la possibilità di sfruttare la dichiarazione di tipo non nullable su un parametro in modo che questa genera automaticamente un controllo null (sebbene ciò avrebbe probabilmente da una decisione di consenso esplicito per evitare un calo delle prestazioni indesiderati a meno che non può essere effettuata in fase di compilazione).

(Ironicamente, in c# 2.0 aggiunti tipi di valore nullable, poiché esistono numerosi casi, ad esempio i dati recuperati da un database, in cui è necessario per consentire a un numero intero contenere valori null. E ora, in c# 7, il team esegue la ricerca per supportare l'opposto di tipi di riferimento).

Una soluzione interessa con supporto dei tipi di riferimento per elementi che non ammette valori null (ad esempio, stringhe! testo) è quello che l'implementazione sarebbe in Common Intermediate Language (CIL). Le due proposte più diffuse sono se eseguirne il mapping a una sintassi di tipo Nullable < T > o utilizzare gli attributi come testo della stringa [ammette valori null]. Quest'ultimo è la scelta migliore.

Tuple

Le tuple sono un'altra funzionalità presi in considerazione per C# 7. Si tratta di un argomento che è risultata in più occasioni per le versioni precedenti del linguaggio, ma ancora non è ancora piuttosto reso nell'ambiente di produzione. L'idea è che sarebbe possibile dichiarare tipi di set di modo che una dichiarazione può contenere più valori e, in modo analogo, i metodi possono restituire più valori. Si consideri il seguente codice di esempio per comprendere il concetto:

public class Person
{
  public readonly (string firstName, int lastName) Names; // a tuple
  public Person((string FirstName, string LastName)) names, int Age)
  {
    Names = names;
  }
}

Come illustrato nell'elenco, con supporto di tuple, è possibile dichiarare un tipo come una tupla, con valori di due (o più). Questo può essere utilizzato qualsiasi tipo di dati può essere sfruttato, tra cui come un campo, parametro, dichiarazione di variabile o anche un metodo viene restituito. Ad esempio, il frammento di codice seguente restituisce una tupla da un metodo:

public (string FirstName, string LastName) GetNames(string! fullName)
{
  string[] names = fullName.Split(" ", 2);
  return (names[0], names[1]);
}
public void Main()
{
  // ...
  (string first, string last) = GetNames("Inigo Montoya");
  // ...
}

In questo elenco è un metodo che restituisce una tupla e una dichiarazione di variabile del primo e l'ultimo che il risultato GetNames viene assegnato a. Si noti che l'assegnazione è in base all'ordine nella tupla (non i nomi delle variabili di destinazione). Prendere in considerazione alcuni approcci alternativi, è necessario utilizzare oggi, ovvero una matrice o raccolta, un tipo personalizzato, i parametri out, ovvero le tuple sono un'opzione allettante.

Sono disponibili numerose opzioni che poteva insieme Tuple. Ecco alcuni presi in considerazione:

  • Le tuple potrebbero disporre denominato o senza nome di proprietà, come in:
var name = ("Inigo", "Montoya")

e:

var name = (first: "John", last: "Doe")
  • Il risultato potrebbe essere un tipo anonimo o variabili esplicite, come in:
var name = (first: "John", last: "Doe")

oppure

(string first, string last) = GetNames("Inigo Montoya")
  • È potenzialmente possibile convertire una matrice a una tupla, come in:
var names = new[]{ "Inigo", "Montoya" }
  • È possibile accedere gli elementi di tupla individuali in base al nome, come in:
Console.WriteLine($”My name is { names.first } { names.last }.”);
  • Tipi di dati potrebbero essere dedotto in cui non appena sono identificati in modo esplicito (seguendo lo stesso approccio utilizzato da tipi anonimi in generale)

Anche se vi sono problemi con le tuple, per la maggior parte seguono strutture già ben definite all'interno del linguaggio, in modo che abbiano abbastanza solido supporto per l'inclusione di C# 7.

Criteri di ricerca

Criteri di ricerca sono anche un argomento di frequente in discussione del team di progettazione C# 7. Forse uno del rendering di questo più comprensibile sarebbe commutatore espanso (e se) istruzioni supportate modelli di espressione in istruzioni case piuttosto che solo costanti. (Per l'istruzione case espanso, il tipo dell'espressione switch sarebbe limitato a tipi che dispongono di valori costanti corrispondenti,). Con criteri di ricerca, si potrebbe interrogare l'espressione switch per un modello, ad esempio se l'espressione switch è un tipo specifico, un tipo con un determinato membro o anche un tipo corrispondente di un "criterio" specifico o un'espressione. Si consideri ad esempio come obj potrebbe essere di tipo Point con un valore di x maggiore di 2:

object obj;
// ...
switch(obj) {
  case 42:
    // ...
  case Color.Red:
    // ...
  case string s:
    // ...
  case Point(int x, 42) where (Y > 42):
    // ...
  case Point(490, 42): // fine
    // ...
  default:
    // ...
}

È interessante notare che, dato espressioni come istruzioni case, anche sarebbe necessaria per consentire le espressioni come argomenti di goto case (istruzioni).

Per supportare il caso di tipo Point, è necessario essere un tipo di membro sul punto di gestione di criteri di ricerca. In questo caso, è necessario è un membro che accetta due argomenti di tipo int. Un membro, ad esempio, ad esempio:

public static bool operator is (Point self out int x, out int y) {...}

Si noti che senza where espressione case punto (490, 42) non Impossibile mai raggiunto, causando il compilatore di generare un errore o avviso.

Uno dei fattori di limitazione dell'istruzione switch è che non restituisce alcun valore, ma piuttosto esegue un blocco di codice. Una funzionalità aggiunta di criteri di ricerca potrebbe essere il supporto per un switchexpression che restituisce un valore, come in:

string text = match (e) { pattern => expression; ... ; default => expression }

Analogamente, i è l'operatore può supportare criteri di ricerca, che consente non solo un tipo di controllo ma supporto possibile per una query per l'esistono di determinati membri su un tipo più generico.

Record

In una continuazione della sintassi di dichiarazione abbreviato "costruttore" considerata (ma in definitiva rifiutati) in c# 6.0, è supportata per l'incorporamento di dichiarazione del costruttore all'interno della definizione di classe, un concetto noto come "record". Ad esempio, consideriamo la seguente dichiarazione:

class Person(string Name, int Age);

Questa istruzione semplice generi automaticamente le operazioni seguenti:

  • Un costruttore:
public Person(string Name, int Age)
{
  this.Name = Name;
  this.Age = Age;
}
  • Proprietà di sola lettura, creando così un tipo immutabile
  • Le implementazioni di uguaglianza (ad esempio GetHashCode, uguale a, operatore operator = =,! = e così via)
  • Un'implementazione predefinita di ToString
  • Corrispondenza al modello di supporto dell'operatore "is"

Anche se viene generata una quantità significativa di codice (considerando soltanto una breve riga di codice creato tutto), la speranza è che può fornire un collegamento in proporzione significativo manualmente che cos'è essenzialmente le implementazioni standard di codifica. Inoltre, tutto il codice può essere considerato "default" in quanto l'implementazione esplicita di una delle relative hanno la precedenza e impedisce la generazione dello stesso membro.

Uno dei problemi più problematici associati record viene illustrato come gestire la serializzazione. Sfruttando presumibilmente record come oggetti di trasferimento dei dati (oggetti DTO) è tipico e ancora non è chiaro cosa, se qualcosa, può essere eseguita per supportare la serializzazione di tale record.

In associazione con il record è supportata con le espressioni. Con le espressioni consentono la creazione di istanze di un nuovo oggetto basato su un oggetto esistente. Data la dichiarazione dell'oggetto utente, ad esempio, è possibile creare una nuova istanza tramite le operazioni seguenti con espressione:

Person inigo = new Person("Inigo Montoya", 42);
Person humperdink = inigo with { Name = "Prince Humperdink" };

Il corrispondente codice generato per l'espressione può essere:

Person humperdink = new Person(Name: "Prince Humperdink", Age: inigo.42 );

Un suggerimento alternativo, tuttavia, è tale piuttosto che a seconda della firma del costruttore per l'espressione, potrebbe essere preferibile convertirlo nella chiamata di un metodo With, come in:

Person humperdink = inigo.With(Name: "Prince Humperdink", Age: inigo.42);

Flussi asincroni

Per migliorare il supporto della programmazione asincrona in c# 7, la nozione di elaborazione asincrone sequenze è molto interessante. Ad esempio, dato un IAsyncEnumerable, con la proprietà Current e un'attività < bool > MoveNextAsync (metodo), è possibile scorrere l'istanza IAsyncEnumerable utilizzo di foreach e che il compilatore di occuparsi della chiamata asincrona di ogni membro nel flusso, l'esecuzione di un'attesa per verificare se è disponibile un altro elemento nella sequenza (probabilmente un canale) al processo. Esistono alcuni aspetti a ciò che occorre valutare il minor dei quali è il peso LINQ potenziali che potrebbe verificarsi con tutti gli operatori di query standard LINQ che restituiscono IAsyncEnumerable. Inoltre, non è determinato come per esporre il supporto CancellationToken e persino Task.ConfigureAwait.

Linguaggio c# nella riga di comando

Nonché un appassionato di come Windows PowerShell rende disponibile in un'interfaccia della riga di comando (CLI) di Microsoft .NET Framework, un'area che sono particolarmente incuriosito (probabilmente la funzionalità preferite presi in considerazione) è il supporto per l'utilizzo di c# nella riga di comando. è un concetto più genericamente parla di supporto per Read, Evaluate, Print, Loop (REPL). Come piacerebbe a tutti, supporto REPL potrebbe essere accompagnato da scripting c# che non richiedono tutte la formalità consueto (ad esempio, la dichiarazione di classe) in scenari semplici che non richiedono tali quelle più complesse. Senza un passaggio di compilazione, REPL richiederebbe nuove direttive per il riferimento di assembly e i pacchetti NuGet, con l'importazione di file aggiuntivi. Supporto per la proposta corrente in fase di definizione:

  • #r per fare riferimento a un assembly aggiuntivi o un pacchetto NuGet. Una variazione sarebbe #r!, che consentirebbe anche di accesso ai membri interni, sebbene con alcuni vincoli. (Questo è destinato a scenari in cui si accede assembly per cui si dispone del codice sorgente.)
  • #l per includere l'intera directory (simile a F #).
  • #load per importare un aggiuntive c# file di script, nello stesso modo, che è necessario aggiungere al progetto ma ora ordine è importante. Si noti che l'importazione di un file con estensione cs potrebbe non essere supportata perché non sono consentiti gli spazi dei nomi in c# script.
  • #time per attivare la diagnostica delle prestazioni durante l'esecuzione.

È possibile prevedere la prima versione di c# REPL rilascio con Visual Studio 2015 Update 1 (insieme a una finestra interattiva aggiornato che supporta lo stesso set di funzionalità). Per ulteriori informazioni consultare Itl.tc/CSREPL, con la colonna mese successivo.

Avvolgendo

Valore dell'anno del materiale è troppo per esplorare tutti il progetto team già, e anche con le idee trattato, sono disponibili molte più informazioni (avvertenze e vantaggi) che devono essere prese in considerazione. Si spera, tuttavia, si disporrà di un'idea di cosa il team sta prendendo in considerazione e come proattivo per migliorare il linguaggio c# già brillante. Se si desidera rivedere le note sulla progettazione di c# 7 direttamente e possibilmente fornire il proprio feedback, è possibile passare in discussione a bit.ly/CSharp7DesignNotes.


Mark Michaelisè fondatore di IntelliTect, dove ha serve come responsabile dell'architettura tecnica e istruttore. Per quasi due decenni lavora un Microsoft MVP e un Microsoft Regional Director poiché 2007. Michaelis serve in diversi software progettazione revisione team Microsoft, tra cui c#, Microsoft Azure, SharePoint e Visual Studio ALM. Ha come relatore a conferenze per gli sviluppatori e ha scritto numerosi libri, tra cui il suo più recente, "Essential c# 6.0 (5 ° edizione)" (itl.tc/EssentialCSharp). È possibile contattarlo su Facebook al facebook.com/Mark.Michaelis, sul suo blog all'indirizzo IntelliTect.com/Mark, su Twitter: @markmichaelis o tramite posta elettronica all'indirizzo mark@IntelliTect.com.

Grazie all'esperto tecnico Microsoft seguente per la revisione di questo articolo: Mads Torgerson