Microsoft annonce la sortie de C# 10 dans le cadre de .NET 6 et Visual Studio 2022.
C# 10 apporte des améliorations aux expressions lambda et plusieurs fonctionnalités « Aujourd'hui, nous sommes heureux d'annoncer la sortie de C# 10 dans le cadre de .NET 6 et Visual Studio 2022 », a indiqué Kathleen Dollard,
Principal Program Manager, .NET. Voici les améliorations et nouveautés apportées par cette version.
Utilisations globales et implicitesLes directives
using simplifient la façon dont vous travaillez avec les espaces de noms. C# 10 inclut une nouvelle directive
using global et des utilisations implicites pour réduire le nombre d'utilisations que vous devez spécifier en haut de chaque fichier.
Directives global usingSi le mot-clé
global apparaît avant une directive
using, cette utilisation s'applique à l'ensemble du projet*:
Vous pouvez utiliser n'importe quelle fonctionnalité de
using dans une directive
using global. Par exemple, l'ajout de
static importe un type et rend les membres du type et les types imbriqués disponibles dans tout votre projet. Si vous utilisez un alias dans votre directive
using, cet alias affectera également l'ensemble de votre projet*:
1 2
| global using static System.Console;
global using Env = System.Environment; |
Vous pouvez mettre
using global dans n'importe quel fichier .cs, y compris Program.cs ou un fichier spécifiquement nommé comme globalusings.cs. Le périmètre de
using global est la compilation en cours, qui correspond généralement au projet en cours.
modificateur staticLa directive
using static nomme un type dont les membres statiques et les types imbriqués vous pouvez accéder sans spécifier de nom de type. La directive
using static a été introduite avec C# 6. Sa syntaxe est la suivante :
using static <nom de type complet>;
Le <nom de type complet> est le nom du type dont les membres statiques et les types imbriqués peuvent être référencés sans spécifier de nom de type. Si vous ne fournissez pas de nom de type qualifié complet (le nom d’espace de noms complet avec le nom de type), C# génère l’erreur de compilateur CS0246: « le type ou le nom d’espace de noms’type/espace de noms’est introuvable (une directive
using ou une référence d'assemblage est-elle manquante ?) ».
La directive
using static s’applique à tout type ayant des membres statiques (ou des types imbriqués), même s’il a également des membres d’instance. Toutefois, les membres d’instance ne peuvent être appelés que par l’instance du type.
Vous pouvez accéder aux membres statiques d'un type sans devoir qualifier l'accès avec le nom du type :
1 2 3 4 5 6 7 8 9
| using static System.Console;
using static System.Math;
class Program
{
static void Main()
{
WriteLine(Sqrt(3*3 + 4*4));
}
} |
En général, quand vous appelez un membre statique, vous indiquez le nom du type, ainsi que le nom du membre. Entrer plusieurs fois le même nom de type pour appeler des membres du type peut produire du code détaillé et peu clair. Par exemple, la définition suivante d’une classe
Circle fait référence à de nombreux membres de la classe
Math :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| using System;
public class Circle
{
public Circle(double radius)
{
Radius = radius;
}
public double Radius { get; set; }
public double Diameter
{
get { return 2 * Radius; }
}
public double Circumference
{
get { return 2 * Radius * Math.PI; }
}
public double Area
{
get { return Math.PI * Math.Pow(Radius, 2); }
}
} |
En éliminant la nécessité de référencer explicitement la classe
Math chaque fois qu’un membre est référencé, la directive
using static génère du code plus propre :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| using System;
using static System.Math;
public class Circle
{
public Circle(double radius)
{
Radius = radius;
}
public double Radius { get; set; }
public double Diameter
{
get { return 2 * Radius; }
}
public double Circumference
{
get { return 2 * Radius * PI; }
}
public double Area
{
get { return PI * Pow(Radius, 2); }
}
} |
using static importe uniquement les membres statiques accessibles et les types imbriqués déclarés dans le type spécifié. Les membres hérités ne sont pas importés. vous pouvez importer à partir de n’importe quel type nommé avec une directive
using static, y compris Visual Basic modules. Si des fonctions de niveau supérieur F# apparaissent dans les métadonnées comme membres statiques d’un type nommé dont le nom est un identificateur C# valide, les fonctions F# peuvent être importées.
using static rend les méthodes d'extension déclarées dans le type spécifié disponibles pour la recherche de méthode d'extension. Toutefois, les noms des méthodes d’extension ne sont pas importés dans la portée pour une référence non qualifiée dans le code.
Les méthodes portant le même nom et qui sont importées à partir de différents types par différentes directives
using static dans la même unité de compilation ou le même espace de noms forment un groupe de méthodes. La résolution de surcharge au sein de ces groupes de méthodes suit des règles C# normales.
L’exemple suivant utilise la directive
using static pour que les membres statiques des classes Console, Math et String soient disponibles sans que vous ayez à spécifier leur nom de type :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| using System;
using static System.Console;
using static System.Math;
using static System.String;
class Program
{
static void Main()
{
Write("Enter a circle's radius: ");
var input = ReadLine();
if (!IsNullOrEmpty(input) && double.TryParse(input, out var radius)) {
var c = new Circle(radius);
string s = "\nInformation about the circle:\n";
s = s + Format(" Radius: {0:N2}\n", c.Radius);
s = s + Format(" Diameter: {0:N2}\n", c.Diameter);
s = s + Format(" Circumference: {0:N2}\n", c.Circumference);
s = s + Format(" Area: {0:N2}\n", c.Area);
WriteLine(s);
}
else {
WriteLine("Invalid input...");
}
}
}
public class Circle
{
public Circle(double radius)
{
Radius = radius;
}
public double Radius { get; set; }
public double Diameter
{
get { return 2 * Radius; }
}
public double Circumference
{
get { return 2 * Radius * PI; }
}
public double Area
{
get { return PI * Pow(Radius, 2); }
}
}
// The example displays the following output:
// Enter a circle's radius: 12.45
//
// Information about the circle:
// Radius: 12.45
// Diameter: 24.90
// Circumference: 78.23
// Area: 486.95 |
Dans cet exemple, la directive
using static aurait également pu être appliquée au type
Double. L’ajout de cette directive permet d’appeler la méthode
TryParse(String, Double) sans spécifier de nom de type. Toutefois, l’utilisation de
TryParse sans nom de type crée un code moins lisible, puisqu’il est nécessaire de vérifier les directives
using static pour déterminer la méthode du type numérique que
TryParse appelle.
ImplicitUsingLa fonctionnalité
ImplicitUsing ajoute automatiquement des directives
global using communes pour le type de projet que vous créez. Pour activer les utilisations implicites, définissez la propriété
ImplicitUsings dans votre fichier .csproj*:
1 2 3 4
| <PropertyGroup>
<!-- Other properties like OutputType and TargetFramework -->
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup> |
Les utilisations implicites sont activées dans les nouveaux modèles .NET 6.
L'ensemble spécifique de directives d'utilisation globales incluses dépend du type d'application que vous créez. Par exemple, les utilisations implicites d'une application console ou d'une bibliothèque de classes sont différentes de celles d'une application ASP.NET.
Combiner les fonctionnalités usingLes directives
using traditionnelles en haut de vos fichiers, les directives
using globales et les utilisations implicites fonctionnent bien ensemble. Les utilisations implicites vous permettent d'inclure les espaces de noms .NET appropriés au type de projet que vous créez avec une seule ligne dans votre fichier de projet. Les directives d'utilisation globales vous permettent d'inclure des espaces de noms supplémentaires pour les rendre disponibles tout au long de votre projet. Les directives
using en haut de vos fichiers de code vous permettent d'inclure des espaces de noms utilisés par quelques fichiers seulement dans votre projet.
Quelle que soit la façon dont elles sont définies, les directives
using supplémentaires augmentent la possibilité d'ambiguïté dans la résolution de noms. Si vous rencontrez ce problème, envisagez d'ajouter un alias ou de réduire le nombre d'espaces de noms que vous importez. Par exemple, vous pouvez remplacer les directives
using globales par des directives using explicites en haut d'un sous-ensemble de fichiers.
Si vous devez supprimer des espaces de noms qui ont été inclus via des utilisations implicites, vous pouvez les spécifier dans votre fichier projet*:
1 2 3
| <ItemGroup>
<Using Remove="System.Threading.Tasks" />
</ItemGroup> |
Vous pouvez également ajouter un espace de noms qui se comporte comme s'il s'agissait de directives
using globales, vous pouvez ajouter des éléments
Using à votre fichier projet, par exemple*:
1 2 3
| <ItemGroup>
<Using Include="System.IO.Pipes" />
</ItemGroup> |
Espaces de noms qui portent sur un fichierDe nombreux fichiers contiennent du code pour un seul espace de noms. À partir de C# 10, vous pouvez inclure un espace de noms en tant qu'instruction, suivi d'un point-virgule et sans les accolades*:
1 2 3 4
| namespace MyCompany.MyNamespace;
class MyClass // Note: no indentation
{ ... } |
Cela simplifie le code et supprime un niveau d'imbrication. Une seule déclaration d'espace de noms à portée de fichier est autorisée, et elle doit intervenir avant que les types ne soient déclarés.
Le mot clé
namespace est utilisé pour déclarer une portée qui contient un ensemble d’objets connexes. Vous pouvez utiliser un espace de noms pour organiser les éléments de code et créer des types globaux uniques.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| namespace SampleNamespace
{
class SampleClass { }
interface ISampleInterface { }
struct SampleStruct { }
enum SampleEnum { a, b }
delegate void SampleDelegate(int i);
namespace Nested
{
class SampleClass2 { }
}
} |
Les déclarations d’espaces de noms avec étendue de fichier vous permettent de déclarer que tous les types d’un fichier se trouvent dans un espace de noms unique. Les déclarations d’espaces de noms avec étendue de fichier sont disponibles avec C# 10. L’exemple suivant est similaire à l’exemple précédent, mais utilise une déclaration d’espace de noms avec étendue de fichier :
1 2 3 4 5 6 7 8 9 10 11 12 13
| using System;
namespace SampleFileScopedNamespace;
class SampleClass { }
interface ISampleInterface { }
struct SampleStruct { }
enum SampleEnum { a, b }
delegate void SampleDelegate(int i); |
L’exemple précédent n’inclut pas d’espace de noms imbriqué. Les espaces de noms de portée de fichier ne peuvent pas inclure de déclarations d’espaces de noms supplémentaires. Vous ne pouvez pas déclarer un espace de noms imbriqué ou un deuxième espace de noms de portée de fichier :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| namespace SampleNamespace;
class AnotherSampleClass
{
public void AnotherSampleMethod()
{
System.Console.WriteLine(
"SampleMethod inside SampleNamespace");
}
}
namespace AnotherNamespace; // Not allowed!
namespace ANestedNamespace // Not allowed!
{
// declarations...
} |
Améliorations des expressions lambda et des groupes de méthodesMicrosoft a apporté plusieurs améliorations aux types et à la syntaxe entourant les lambdas. L'entreprise s'attend à ce que ceux-ci soient largement utiles, et l'un des scénarios de conduite a été de rendre les API ASP.NET minimales encore plus simples.
Types naturels pour les lambdasLes expressions lambda ont maintenant parfois un type « naturel ». Cela signifie que le compilateur peut souvent déduire le type de l'expression lambda.
Jusqu'à présent, une expression lambda devait être convertie en un délégué ou un type d'expression. Dans la plupart des cas, vous utiliserez l'un des types de délégués surchargés
Func<...> ou
Action<...> dans la BCL*:
Func<string, int> parse = (string s) => int.Parse(s);
À partir de C# 10, cependant, si un lambda n'a pas un tel « type cible », l'éditeur va essayer d'en calculer un pour vous*:
var parse = (string s) => int.Parse(s);
Vous pouvez survoler
var parse dans votre éditeur et voir que le type est toujours
Func<string, int>. En général, le compilateur utilisera un délégué Func ou Action disponible, s'il en existe un approprié. Sinon, il synthétisera un type délégué (par exemple, lorsque vous avez des paramètres ref ou que vous avez un grand nombre de paramètres).
Tous les lambdas n'ont pas de types naturels - certains n'ont tout simplement pas assez d'informations sur les types. Par exemple, omettre les types de paramètres laissera le compilateur incapable de décider quel type de délégué utiliser*:
var parse = s => int.Parse(s); // ERROR: Not enough type info in the lambda
Le type naturel des lambdas signifie qu'ils peuvent être affectés à un type plus faible, tel que
objet ou
Delegate*:
1 2
| object parse = (string s) => int.Parse(s); // Func<string, int>
Delegate parse = (string s) => int.Parse(s); // Func<string, int> |
En ce qui concerne les arbres d'expression, Microsoft fait une combinaison de typage «*cible*» et «*naturel*». Si le type cible est LambdaExpression ou l'Expression non générique (type de base pour toutes les arborescences d'expressions) et que lambda a un type délégué naturel D, l'éditeur produira à la place une Expression<D>*:
1 2
| LambdaExpression parseExpr = (string s) => int.Parse(s); // Expression<Func<string, int>>
Expression parseExpr = (string s) => int.Parse(s); // Expression<Func<string, int>> |
Types naturels pour les groupes de méthodesLes groupes de méthodes (c'est-à-dire les noms de méthodes sans listes d'arguments) ont maintenant aussi parfois un type naturel. Vous avez toujours pu convertir un groupe de méthodes en un type délégué compatible*:
1 2
| Func<int> read = Console.Read;
Action<string> write = Console.Write; |
Maintenant, si le groupe de méthodes n'a qu'une seule surcharge, il aura un type naturel*:
1 2
| var read = Console.Read; // Just one overload; Func<int> inferred
var write = Console.Write; // ERROR: Multiple overloads, can't choose |
Source :
MicrosoftVoir aussi
Microsoft présente Visual Studio 2022, la prochaine version majeure de Visual Studio. La première Public Preview sera disponible cet été
Visual Studio 2022 Preview 4 est disponible et s'accompagne d'améliorations sur la productivité personnelle et d'équipe, le chargement à chaud dans ASP.NET Core et la gestion de thèmes
Visual Studio 2022 64-bit Preview 2 est disponible, elle apporte de nouvelles fonctionnalités et permet de créer des applications multiplateformes
Visual Studio 2022 Preview 3 est disponible et s'accompagne de la possibilité d'effectuer des tests à distance sur plusieurs plateformes, ainsi que d'une amélioration du thème sombre
Microsoft améliore l'expérience .NET Hot Reload sur Visual Studio 2022, la version de son éditeur qui va bénéficier de l'expérience complète
8 |
0 |