Didacticiel : migrer du code existant avec des types de référence NullableTutorial: Migrate existing code with nullable reference types

C# 8 introduit les types référence Nullable, qui viennent compléter les types référence de la même façon que les types valeur Nullable complètent les types valeur.C# 8 introduces nullable reference types, which complement reference types the same way nullable value types complement value types. Pour déclarer une variable comme étant un type référence Nullable, on ajoute ? au type.You declare a variable to be a nullable reference type by appending a ? to the type. Par exemple, string? représente une string Nullable.For example, string? represents a nullable string. Vous pouvez utiliser ces nouveaux types pour exprimer plus clairement votre intention de conception : certaines variables doivent toujours avoir une valeur, d’autres peuvent ne pas en avoir.You can use these new types to more clearly express your design intent: some variables must always have a value, others may be missing a value. Toutes les variables existantes d’un type de référence sont interprétées comme un type de référence non nullable.Any existing variables of a reference type would be interpreted as a non-nullable reference type.

Dans ce tutoriel, vous allez apprendre à :In this tutorial, you'll learn how to:

  • Activer les vérifications de référence null lorsque vous travaillez avec du code.Enable null reference checks as you work with code.
  • Diagnostiquer et corriger les différents avertissements liés aux valeurs null.Diagnose and correct different warnings related to null values.
  • Gérer l’interface entre les contextes compatibles avec nullable et non compatibles avec nullable.Manage the interface between nullable enabled and nullable disabled contexts.
  • Contrôler les contextes d’annotation nullable.Control nullable annotation contexts.

Configuration requisePrerequisites

Vous devez configurer votre ordinateur pour exécuter .NET Core, y compris le C# compilateur 8,0.You’ll need to set up your machine to run .NET Core, including the C# 8.0 compiler. Le C# compilateur 8 est disponible à partir de Visual Studio 2019 version 16,3 ou du Kit de développement logiciel (SDK) .net Core 3,0.The C# 8 compiler is available starting with Visual Studio 2019 version 16.3 or .NET Core 3.0 SDK.

Ce tutoriel suppose de connaître C# et .NET, y compris Visual Studio ou l’interface CLI .NET Core.This tutorial assumes you're familiar with C# and .NET, including either Visual Studio or the .NET Core CLI.

Explorer l’exemple d’applicationExplore the sample application

L’exemple d’application que vous allez migrer est une application web de lecteur de flux RSS.The sample application that you'll migrate is an RSS feed reader web app. Il lit à partir d’un flux RSS unique et affiche des résumés des articles les plus récents.It reads from a single RSS feed and displays summaries for the most recent articles. Vous pouvez sélectionner n’importe quel article pour visiter le site.You can select any of the articles to visit the site. L’application est relativement nouvelle, mais a été écrite avant que les types de référence nullable ne soient disponibles.The application is relatively new but was written before nullable reference types were available. Les décisions de conception de l’application constituent des principes solides, mais ne tirent pas parti de cette fonctionnalité de langage importante.The design decisions for the application represented sound principles, but don't take advantage of this important language feature.

L’exemple d’application inclut une bibliothèque de tests unitaires qui valide les fonctionnalités principales de l’application.The sample application includes a unit test library that validates the major functionality of the app. Ce projet facilite la mise à niveau en toute sécurité, si vous modifiez l’implémentation basée sur les avertissements générés.That project will make it easier to upgrade safely, if you change any of the implementation based on the warnings generated. Vous pouvez télécharger l’exemple de démarrage à partir du référentiel GitHub dotnet/samples.You can download the starter code from the dotnet/samples GitHub repository.

Votre objectif de migration d’un projet doit être de tirer parti des nouvelles fonctionnalités de langage afin d’exprimer clairement votre intention sur la possibilité de valeur null des variables et faire cela de manière à ce que le compilateur ne génère d’avertissements lorsque le contexte d’annotation nullable et le contexte d’avertissement nullable sont définis sur enabled.Your goal migrating a project should be to leverage the new language features so that you clearly express your intent on the nullability of variables, and do so in such a way that the compiler doesn't generate warnings when you have the nullable annotation context and nullable warning context set to enabled.

Mettre à niveau les projets vers C# 8Upgrade the projects to C# 8

La première étape consiste à déterminer l’étendue de la tâche de migration.A good first step is to determine the scope of the migration task. Commencez par la mise à niveau du projet vers C# 8.0 (ou version ultérieure).Start by upgrading the project to C# 8.0 (or newer). Ajoutez l’élément LangVersion aux deux fichiers csproj pour le projet web et le projet de test unitaire :Add the LangVersion element to both csproj files for the web project and the unit test project:

<LangVersion>8.0</LangVersion>

La mise à niveau de la version de langage sélectionne C# 8.0, mais n’active pas le contexte d’annotation nullable ou le contexte d’avertissement nullable.Upgrading the language version selects C# 8.0, but does not enable the nullable annotation context or the nullable warning context. Régénérez le projet pour vous assurer qu’il se génère sans avertissement.Rebuild the project to ensure that it builds without warnings.

Une bonne étape suivante consiste à activer le contexte d’annotation nullable et de voir combien d’avertissements sont générés.A good next step is to turn on the nullable annotation context and see how many warnings are generated. Ajoutez l’élément suivant aux fichiers csproj dans la solution, directement sous l’élément LangVersion :Add the following element to both csproj files in the solution, directly under the LangVersion element:

<Nullable>enable</Nullable>

Effectuez une build de test et notez la liste d’avertissements.Do a test build, and notice the warning list. Dans cette petite application, le compilateur génère cinq avertissements, il est donc probable que vous laissiez le contexte d’annotation nullable activé et commenciez à résoudre les avertissements pour l’ensemble du projet.In this small application, the compiler generates five warnings, so it's likely you'd leave the nullable annotation context enabled and start fixing warnings for the entire project.

Cette stratégie fonctionne uniquement pour les projets plus petits.That strategy works only for smaller projects. Pour tous les projets plus volumineux, le nombre d’avertissements générés par l’activation du contexte d’annotation nullable pour l’intégralité de la base de code rend plus difficile de résoudre les avertissements de manière systématique.For any larger projects, the number of warnings generated by enabling the nullable annotation context for the entire codebase makes it harder to fix the warnings systematically. Pour les grands projets d’entreprise, vous aurez souvent besoin de migrer un projet à la fois.For larger enterprise projects, you'll often want to migrate one project at a time. Dans chaque projet, migrez une classe ou un fichier à la fois.In each project, migrate one class or file at a time.

Les avertissements contribuent à découvrir l’intention de conception d’origineWarnings help discover original design intent

Il existe deux classes qui génèrent plusieurs avertissements.There are two classes that generate multiple warnings. Commencez avec la classe NewsStoryViewModel.Start with the NewsStoryViewModel class. Supprimez l’élément Nullable des deux fichiers csproj afin de pouvoir limiter l’étendue des avertissements aux sections de code sur lesquelles vous travaillez.Remove the Nullable element from both csproj files so that you can limit the scope of warnings to the sections of code you're working with. Ouvrez le fichier NewsStoryViewModel.cs, puis ajoutez les directives suivantes pour activer le contexte d’annotation nullable pour NewsStoryViewModel et restaurez-le en suivant cette définition de classe :Open the NewsStoryViewModel.cs file and add the following directives to enable the nullable annotation context for the NewsStoryViewModel and restore it following that class definition:

#nullable enable
public class NewsStoryViewModel
{
    public DateTimeOffset Published { get; set; }
    public string Title { get; set; }
    public string Uri { get; set; }
}
#nullable restore

Ces deux directives vous aident à concentrer vos efforts de migration.These two directives help you focus your migration efforts. Les avertissements nullables sont générés pour la zone de code sur laquelle vous travaillez activement.The nullable warnings are generated for the area of code you're actively working on. Vous les laissez activés jusqu’à ce que vous soyez prêt à activer les avertissements pour l’ensemble du projet.You'll leave them on until you're ready to turn on the warnings for the entire project. Vous devriez utiliser restore plutôt que la valeur disable afin de ne pas désactiver accidentellement le contexte ultérieurement lorsque de l’activation des annotations nullables pour la totalité du projet.You should use the restore rather than disable value so that you don't accidentally disable the context later when you've turned on nullable annotations for the entire project. Une fois que vous avez activé le contexte d’annotation nullable pour la totalité du projet, vous pouvez supprimer tous les pragmas #nullable à partir de ce projet.Once you've turned on the nullable annotation context for the entire project, you can remove all the #nullable pragmas from that project.

La classe NewsStoryViewModel est un objet de transfert de données (DTO) et deux des propriétés sont des chaînes de lecture/écriture :The NewsStoryViewModel class is a data transfer object (DTO) and two of the properties are read/write strings:

public class NewsStoryViewModel
{
    public DateTimeOffset Published { get; set; }
    public string Title { get; set; }
    public string Uri { get; set; }
}

Ces deux propriétés provoquent CS8618, « Propriété non-nullable initialisée ».These two properties cause CS8618, "Non-nullable property is uninitialized". Cela est suffisamment clair : les deux propriétés string ont la valeur par défaut null lorsqu’un NewsStoryViewModel est construit.That's clear enough: both string properties have the default value of null when a NewsStoryViewModel is constructed. Il est important de découvrir comment les objets NewsStoryViewModel sont construits.What's important to discover is how NewsStoryViewModel objects are constructed. En examinant cette classe, vous ne pouvez pas savoir si la valeur null fait partie de la conception, ou si ces objets sont définis sur des valeurs non null lors de leur création.Looking at this class, you can't tell if the null value is part of the design, or if these objects are set to non-null values whenever one is created. Les articles de presse sont créés dans la méthode GetNews de la classe NewsService :The news stories are created in the GetNews method of the NewsService class:

ISyndicationItem item = await feedReader.ReadItem();
var newsStory = _mapper.Map<NewsStoryViewModel>(item);
news.Add(newsStory);

Il se passe beaucoup de choses dans le bloc de code précédent.There's quite a bit going on in the preceding block of code. Cette application utilise le package NuGet AutoMapper pour construire un élément d’article de presse à partir d’un ISyndicationItem.This application uses the AutoMapper NuGet package to construct a news item from an ISyndicationItem. Vous avez découvert que les éléments d’articles de presse sont construits et que les propriétés sont définies dans cette seule instruction.You've discovered that the news story items are constructed and the properties are set in that one statement. Cela signifie que la conception de NewsStoryViewModel indique que ces propriétés ne doivent jamais avoir la valeur null.That means the design for the NewsStoryViewModel indicates that these properties should never have the null value. Ces propriétés doivent être des types de référence non nullable.These properties should be nonnullable reference types. C’est ce qui correspond le mieux à l’intention de conception d’origine.That best expresses the original design intent. En fait, tout NewsStoryViewModel est correctement instancié avec des valeurs non null.In fact, any NewsStoryViewModel is correctly instantiated with non-null values. Ce qui fait du code d’initialisation suivant un correctif valide :That makes the following initialization code a valid fix:

public class NewsStoryViewModel
{
    public DateTimeOffset Published { get; set; }
    public string Title { get; set; } = default!;
    public string Uri { get; set; } = default!;
}

L’attribution de Title et Uri à default qui est null pour le type string ne change pas le comportement d’exécution du programme.The assignment of Title and Uri to default which is null for the string type doesn't change the runtime behavior of the program. NewsStoryViewModel est toujours construit avec des valeurs null, mais maintenant le compilateur ne signale aucun avertissement.The NewsStoryViewModel is still constructed with null values, but now the compiler reports no warnings. L’opérateur indulgent en null, le caractère ! qui suit l’expression default indique au compilateur que l’expression précédente n’est pas null.The null-forgiving operator, the ! character following the default expression tells the compiler that the preceding expression is not null. Cette technique peut être utile lorsque d’autres modifications forcent beaucoup plus les modifications apportées à une base de code, mais dans cette application, il existe une solution relativement rapide et plus performante : faire de la NewsStoryViewModel un type immuable dans lequel toutes les propriétés sont définies dans le constructeur.This technique may be expedient when other changes force much larger changes to a code base, but in this application there is a relatively quick and better solution: Make the NewsStoryViewModel an immutable type where all the properties are set in the constructor. Dans NewsStoryViewModel, effectuez les changements suivants :Make the following changes to the NewsStoryViewModel:

#nullable enable
    public class NewsStoryViewModel
    {
        public NewsStoryViewModel(DateTimeOffset published, string title, string uri) =>
            (Published, Title, Uri) = (published, title, uri);

        public DateTimeOffset Published { get; }
        public string Title { get; }
        public string Uri { get; }
    }
#nullable restore

Une fois cette opération effectuée, vous devez mettre à jour le code qui configure AutoMapper afin qu’il utilise le constructeur, plutôt que de définir des propriétés.Once that's done, you need to update the code that configures the AutoMapper so that it uses the constructor rather than setting properties. Ouvrez NewsService.cs et recherchez le code suivant en bas du fichier :Open NewsService.cs and look for the following code at the bottom of the file:

public class NewsStoryProfile : Profile
{
    public NewsStoryProfile()
    {
        // Create the AutoMapper mapping profile between the 2 objects.
        // ISyndicationItem.Id maps to NewsStoryViewModel.Uri.
        CreateMap<ISyndicationItem, NewsStoryViewModel>()
            .ForMember(dest => dest.Uri, opts => opts.MapFrom(src => src.Id));
    }
}

Ce code mappe les propriétés de l’objet ISyndicationItem aux propriétés NewsStoryViewModel.That code maps properties of the ISyndicationItem object to the NewsStoryViewModel properties. Vous souhaitez qu’AutoMapper assure le mappage à l’aide d’un constructeur à la place.You want the AutoMapper to provide the mapping using a constructor instead. Remplacez le code ci-dessus par la configuration Automapper suivante :Replace the above code with the following automapper configuration:

#nullable enable
    public class NewsStoryProfile : Profile
    {
        public NewsStoryProfile()
        {
            // Create the AutoMapper mapping profile between the 2 objects.
            // ISyndicationItem.Id maps to NewsStoryViewModel.Uri.
            CreateMap<ISyndicationItem, NewsStoryViewModel>()
                .ForCtorParam("uri", opt => opt.MapFrom(src => src.Id));
        }

Notez qu’étant donné que cette classe est petite, et que vous l’avez examinée avec soin, vous devez activer la directive #nullable enable au-dessus de cette déclaration de classe.Notice that because this class is small, and you've examined carefully, you should turn on the #nullable enable directive above this class declaration. La modification apportée au constructeur peut avoir rompu quelque chose, il est donc judicieux d’exécuter tous les tests et de tester l’application avant de continuer.The change to the constructor could have broken something, so it's worthwhile to run all the tests and test the application before moving on.

Le premier ensemble de modifications vous a montré comment effectuer la détection lorsque la conception d’origine indiquait que les variables ne devaient pas être définies sur null.The first set of changes showed you how to discover when the original design indicated that variables shouldn't be set to null. Cette technique est appelée correcte par construction.The technique is referred to as correct by construction. Vous déclarez qu’un objet et ses propriétés ne peuvent pas être null quand il est construit.You declare that an object and its properties cannot be null when it's constructed. L’analyse du flux du compilateur fournit la garantie que ces propriétés ne sont pas définies sur null après la construction.The compiler's flow analysis provides assurance that those properties aren't set to null after construction. Notez que ce constructeur est appelé par du code externe, que ce code oublie la valeur nullable.Note that this constructor is called by external code, and that code is nullable oblivious. La nouvelle syntaxe ne fournit pas la vérification lors de l’exécution.The new syntax doesn't provide runtime checking. Le code externe peut contourner l’analyse du flux du compilateur.External code might circumvent the compiler's flow analysis.

Parfois, la structure d’une classe fournit des différents indices sur l’intention.Other times, the structure of a class provides different clues to the intent. Ouvrez le fichier Error.cshtml.cs dans le dossier Pages.Open the Error.cshtml.cs file in the Pages folder. ErrorViewModel contient le code suivant :The ErrorViewModel contains the following code:

public class ErrorModel : PageModel
{
    public string RequestId { get; set; }

    public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);

    public void OnGet()
    {
        RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
    }
}

Ajouter la directive #nullable enable avant la déclaration de classe et une directive #nullable restore après.Add the #nullable enable directive before the class declaration, and a #nullable restore directive after it. Vous obtiendrez un avertissement indiquant que RequestId n’est pas initialisé.You'll get one warning that RequestId is not initialized. En examinant la classe, vous devez décider que la propriété RequestId doit avoir la valeur null dans certains cas.By looking at the class, you should decide that the RequestId property should be null in some cases. L’existence de la propriété ShowRequestId indique que des valeurs manquantes sont possibles.The existence of the ShowRequestId property indicates that missing values are possible. Étant donné que null est valide, ajoutez ? sur le type string pour indiquer que la propriété RequestId est un type de référence nullable.Because null is valid, add the ? on the string type to indicate the RequestId property is a nullable reference type. La classe finale se présente comme suit :The final class looks like the following example:

#nullable enable
    public class ErrorModel : PageModel
    {
        public string? RequestId { get; set; }

        public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);

        public void OnGet()
        {
            RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
        }
    }
#nullable restore

Vérifiez les utilisations de la propriété, et vous voyez que dans la page associée, la présence de la valeur null est vérifiée dans la propriété avant de la restituer dans le balisage.Check for the uses of the property, and you see that in the associated page, the property is checked for null before rendering it in markup. C’est une utilisation sécurisée d’un type de référence nullable, donc vous en avez terminé avec cette classe.That's a safe use of a nullable reference type, so you're done with this class.

La correction des valeurs null entraîne une modificationFixing nulls causes change

Fréquemment, le correctif pour un ensemble d’avertissements crée de nouveaux avertissements dans le code connexe.Frequently, the fix for one set of warnings creates new warnings in related code. Nous allons voir les avertissements en action en corrigeant la classe index.cshtml.cs.Let's see the warnings in action by fixing the index.cshtml.cs class. Ouvrez le fichier index.cshtml.cs et examinez le code.Open the index.cshtml.cs file and examine the code. Ce fichier contient le code sous-jacent à la page d’index :This file contains the code behind for the index page:

public class IndexModel : PageModel
{
    private readonly NewsService _newsService;

    public IndexModel(NewsService newsService)
    {
        _newsService = newsService;
    }

    public string ErrorText { get; private set; }

    public List<NewsStoryViewModel> NewsItems { get; private set; }

    public async Task OnGet()
    {
        string feedUrl = Request.Query["feedurl"];

        if (!string.IsNullOrEmpty(feedUrl))
        {
            try
            {
                NewsItems = await _newsService.GetNews(feedUrl);
            }
            catch (UriFormatException)
            {
                ErrorText = "There was a problem parsing the URL.";
                return;
            }
            catch (WebException ex) when (ex.Status == WebExceptionStatus.NameResolutionFailure)
            {
                ErrorText = "Unknown host name.";
                return;
            }
            catch (WebException ex) when (ex.Status == WebExceptionStatus.ProtocolError)
            {
                ErrorText = "Syndication feed not found.";
                return;
            }
            catch (AggregateException ae)
            {
                ae.Handle((x) =>
                {
                    if (x is XmlException)
                    {
                        ErrorText = "There was a problem parsing the feed. Are you sure that URL is a syndication feed?";
                        return true;
                    }
                    return false;
                });
            }
        }
    }
}

Ajoutez la directive #nullable enable et vous verrez deux avertissements.Add the #nullable enable directive and you'll see two warnings. Ni la propriété ErrorText ni la propriété NewsItems ne sont initialisées.Neither the ErrorText property nor the NewsItems property is initialized. Un examen de cette classe vous permettra de croire que les deux propriétés doivent être des types de référence Nullable : les deux ont des méthodes setter privées.An examination of this class would lead you to believe that both properties should be nullable reference types: Both have private setters. Une seule exactement est attribuée dans la méthode OnGet.Exactly one is assigned in the OnGet method. Avant d’apporter des modifications, examinez les consommateurs de ces deux propriétés.Before making changes, look at the consumers of both properties. Dans la page elle-même, ErrorText est comparé à la valeur null avant de générer le balisage d’éventuelles erreurs.In the page itself, the ErrorText is checked against null before generating markup for any errors. La collection NewsItems est vérifiée par rapport à null et afin de garantir que la collection comporte des éléments.The NewsItems collection is checked against null, and checked to ensure the collection has items. Un correctif rapide serait d’attribuer le type de référence nullable aux deux propriétés.A quick fix would be to make both properties nullable reference types. Un meilleur correctif consisterait à attribuer un type de référence non nullable à la collection et d’ajouter des éléments à la collection existante lors de la récupération des articles de presse.A better fix would be to make the collection a nonnullable reference type, and add items to the existing collection when retrieving news. Le premier correctif consiste à ajouter ? au type string pour ErrorText :The first fix is to add the ? to the string type for the ErrorText:

public string? ErrorText { get; private set; }

Cette modification ne se propage pas à d’autre code, étant donné que tout accès à la propriété ErrorText a été déjà protégé par les contrôles de la valeur null.That change won't ripple through other code, because any access to the ErrorText property was already guarded by null checks. Ensuite, initialisez la liste NewsItems et supprimez la méthode setter de propriété, pour en faire une propriété en lecture seule :Next, initialize the NewsItems list and remove the property setter, making it a readonly property:

public List<NewsStoryViewModel> NewsItems { get; } = new List<NewsStoryViewModel>();

Cela a résolu l’avertissement, mais a introduit une erreur.That fixed the warning but introduced an error. La liste NewsItems est désormais correcte par construction, mais le code qui définit la liste dans OnGet doit changer pour correspondre à la nouvelle API.The NewsItems list is now correct by construction, but the code that sets the list in OnGet must change to match the new API. Au lieu d’une attribution, appelez AddRange pour ajouter les éléments d’articles de presse à la liste existante :Instead of an assignment, call AddRange to add the news items to the existing list:

NewsItems.AddRange(await _newsService.GetNews(feedUrl));

Utiliser AddRange au lieu d’une attribution signifie que la méthode GetNews peut retourner IEnumerable au lieu de List.Using AddRange instead of an assignment means that the GetNews method can return an IEnumerable instead of a List. Cela permet d’économiser une attribution.That saves one allocation. Modifiez la signature de la méthode et supprimez l’appel ToList, comme indiqué dans l’exemple de code suivant :Change the signature of the method, and remove the ToList call, as shown in the following code sample:

public async Task<IEnumerable<NewsStoryViewModel>> GetNews(string feedUrl)
{
    var news = new List<NewsStoryViewModel>();
    var feedUri = new Uri(feedUrl);

    using (var xmlReader = XmlReader.Create(feedUri.ToString(),
           new XmlReaderSettings { Async = true }))
    {
        try
        {
            var feedReader = new RssFeedReader(xmlReader);

            while (await feedReader.Read())
            {
                switch (feedReader.ElementType)
                {
                    // RSS Item
                    case SyndicationElementType.Item:
                        ISyndicationItem item = await feedReader.ReadItem();
                        var newsStory = _mapper.Map<NewsStoryViewModel>(item);
                        news.Add(newsStory);
                        break;

                    // Something else
                    default:
                        break;
                }
            }
        }
        catch (AggregateException ae)
        {
            throw ae.Flatten();
        }
    }

    return news.OrderByDescending(story => story.Published);
}

La modification de la signature rompt aussi l’un des tests.Changing the signature breaks one of tests as well. Ouvrez le fichier NewsServiceTests.cs dans le dossier Services du projet SimpleFeedReader.Tests.Open the NewsServiceTests.cs file in the Services folder of the SimpleFeedReader.Tests project. Accédez au test Returns_News_Stories_Given_Valid_Uri et modifiez le type de la variable result sur IEnumerable<NewsItem>.Navigate to the Returns_News_Stories_Given_Valid_Uri test and change the type of the result variable to IEnumerable<NewsItem>. La modification du type signifie que la propriété Count n’est plus disponible, par conséquent, remplacez la propriété Count dans Assert avec un appel à Any() :Changing the type means the Count property is no longer available, so replace the Count property in the Assert with a call to Any():

// Act
IEnumerable<NewsStoryViewModel> result =
    await _newsService.GetNews(feedUrl);

// Assert
Assert.True(result.Any());

Vous devrez ajouter une instruction using System.Linq au début du fichier également.You'll need to add a using System.Linq statement to the beginning of the file as well.

Cet ensemble de modifications met en évidence une attention particulière lors de la mise à jour de code qui inclut des instanciations génériques.This set of changes highlights special consideration when updating code that includes generic instantiations. La liste et les éléments dans la liste sont de type non nullable.Both the list and the elements in the list of non-nullable types. L’un ou les deux peuvent être de type nullable.Either or both could be nullable types. Toutes les déclarations suivantes sont autorisées :All the following declarations are allowed:

  • List<NewsStoryViewModel> : liste non nullable de modèles d’affichage non nullable.List<NewsStoryViewModel>: nonnullable list of nonullable view models.
  • List<NewsStoryViewModel?> : liste non nullable de modèles d’affichage nullable.List<NewsStoryViewModel?>: nonnullable list of nullable view models.
  • List<NewsStoryViewModel>? : liste nullable de modèles d’affichage non nullable.List<NewsStoryViewModel>?: nullable list of nonnullable view models.
  • List<NewsStoryViewModel?>? : liste nullable de modèles d’affichage nullable.List<NewsStoryViewModel?>?: nullable list of nullable view models.

Interfaces avec du code externeInterfaces with external code

Vous avez apporté des modifications à la classe NewsService, donc activez l’annotation #nullable enable pour cette classe.You've made changes to the NewsService class, so turn on the #nullable enable annotation for that class. Cela ne génère aucun nouvel avertissements.This won't generate any new warnings. Toutefois, l’examen attentif de la classe permet d’illustrer certaines des limitations de l’analyse du flux du compilateur.However, careful examination of the class helps to illustrate some of the limitations of the compiler's flow analysis. Examinez le constructeur :Examine the constructor:

public NewsService(IMapper mapper)
{
    _mapper = mapper;
}

Le paramètre IMapper est typé comme référence non nullable.The IMapper parameter is typed as a nonnullable reference. Il est appelé par le code d’infrastructure ASP.NET Core, donc le compilateur ne sait pas vraiment que IMapper ne sera jamais null.It's called by ASP.NET Core infrastructure code, so the compiler doesn't really know that the IMapper will never be null. Le conteneur d’injection de dépendance (DI) ASP.NET Core par défaut lève une exception s’il ne peut pas résoudre un service nécessaire, afin que le code soit correct.The default ASP.NET Core dependency injection (DI) container throws an exception if it can't resolve a necessary service, so the code is correct. Le compilateur ne peut pas valider tous les appels à vos API publiques, même si votre code est compilé avec des contextes d’annotation nullable activés.The compiler can't validate all calls to your public APIs, even if your code is compiled with nullable annotation contexts enabled. En outre, vos bibliothèques peuvent être utilisées par des projets qui n’utilisent pas encore des types de référence nullable.Furthermore, your libraries may be consumed by projects that have not yet opted into using nullable reference types. Validez les entrées dans les API publiques même si vous les avez déclarées en tant que types non nullable.Validate inputs to public APIs even though you've declared them as nonnullable types.

Obtenir le codeGet the code

Vous avez résolu les avertissements que vous avez identifiés dans la compilation du test initial, donc vous pouvez désormais activer le contexte d’annotation nullable pour les deux projets.You've fixed the warnings you identified in the initial test compile, so now you can turn on the nullable annotation context for both projects. Régénérez les projets ; le compilateur ne signale aucun avertissement.Rebuild the projects; the compiler reports no warnings. Vous pouvez obtenir le code pour le projet terminé dans le référentiel GitHub dotnet/samples.You can get the code for the finished project in the dotnet/samples GitHub repository.

Les nouvelles fonctionnalités qui prennent en charge les types de référence nullable vous aident à trouver et à corriger les erreurs potentielles dans la façon dont vous gérez les valeurs null dans votre code.The new features that support nullable reference types help you find and fix potential errors in how you handle null values in your code. L’activation du contexte d’annotation nullable vous permet d’exprimer votre intention de conception : certaines variables ne doivent jamais être null, d’autres variables peuvent contenir des valeurs null.Enabling the nullable annotation context allows you to express your design intent: some variables should never be null, other variables may contain null values. Ces fonctionnalités facilitent la déclaration de votre intention de conception.These features make it easier for you to declare your design intent. De même, le contexte d’avertissement nullable indique au compilateur d’émettre des avertissements lorsque vous avez enfreint cette intention.Similarly, the nullable warning context instructs the compiler to issue warnings when you have violated that intent. Ces avertissements vous guident pour effectuer des mises à jour qui rendent votre code plus robuste et moins susceptible de lever une NullReferenceException pendant l’exécution.Those warnings guide you to make updates that make your code more resilient and less likely to throw a NullReferenceException during execution. Vous pouvez contrôler l’étendue de ces contextes afin de vous concentrer sur des zones locales de code à migrer alors que la base de code restante reste intacte.You can control the scope of these contexts so that you can focus on local areas of code to migrate while the remaining codebase is untouched. Dans la pratique, vous pouvez intégrer cette tâche de migration dans une maintenance régulière de vos classes.In practice, you can make this migration task a part of regular maintenance to your classes. Ce tutoriel a présenté le processus de migration d’une application pour utiliser des types de référence nullable.This tutorial demonstrated the process to migrate an application to use nullable reference types. Vous pouvez explorer un exemple réel plus complet de ce processus en examinant la demande de tirage effectuée par Jon Skeet pour incorporer les types de référence nullable dans NodaTime.You can explore a larger real-world example of this process by examining the PR Jon Skeet made to incorporate nullable reference types into NodaTime. En outre, vous pouvez également découvrir des techniques permettant d’utiliser des types de référence Nullable avec Entity Framework Core dans Entity Framework Core-Working avec des types de référence Nullable.Or just In addition, you can learn techniques for using nullable reference types with Entity Framework Core in Entity Framework Core - Working with nullable reference types.