IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Différence Nullable<Something> et Something?


Sujet :

C#

  1. #1
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 744
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 744
    Points : 5 434
    Points
    5 434
    Par défaut Différence Nullable<Something> et Something?
    Bonjour,

    Jusqu'à présent j'ai toujours pensé qu'il n'y avait aucune différence entre Nullable<Something> et Something?.
    Mais sur mon projet (en Core 6, si l'information peut servir), j'ai un message d'erreur CS0453 si j'utilise la version longue.

    Erreur :
    The type 'Employee' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable<T>'
    Le code est le suivant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
        public class Employee
        {
            public Guid Id { get; set; }
     
            public String FirstName { get; set; } = String.Empty;
     
            public String LastName { get; set; } = String.Empty;
     
            public String Mail { get; set; } = String.Empty;
     
            public String Password { get; set; } = String.Empty;
     
            public Int32 Level { get; set; } = 0;
     
            public Nullable<Guid> ManagerId { get; set; }
     
            public virtual Nullable<Employee> Manager { get; set; } // <= Erreur CS0453
            //public virtual Employee? Manager { get; set; } // <= OK
     
            public virtual ICollection<Employee> Employees { get; } = new List<Employee>();
        }
    Est-ce que quelqu'un à une explication ?
    Merci.

  2. #2
    Expert confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2009
    Messages
    2 032
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2009
    Messages : 2 032
    Points : 5 476
    Points
    5 476
    Par défaut
    J'ai fait un projet test tout récemment sur .net core 6 et j'avoue avoir été interpelé par des warnings dans tous les sens.
    Il semble que ça vienne de c# 8.
    https://cdiese.fr/csharp8-nullable-references/

    J'ai pas encore vraiment compris comment je dois gérer ça "proprement". En l'état ça m'embête plus qu'autre chose et j'ai vraiment du mal à comprendre l'avantage.

    Je remarque aussi que du coup il n'y a plus de .HasValue, je me demande comment est géré la rétrocompatibilité.

  3. #3
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 177
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 177
    Points : 25 125
    Points
    25 125
    Par défaut
    int? est une façon simple d'écrire Nullable<int>
    donc c'est bien la même chose à la compilation, c'est un syntaxic sugar
    Nullable (et donc le suffixe ?) ne sont autorisés que sur des types struct comme on peut le voir dans le code source de c#
    public struct Nullable<T> where T : struct=> donc les types par valeur mais pas les types par référence (class, string...)

    sur les projets .net 6 et après (peut etre avant ?) il y a un nouveau paradigme, c# considère que rien n'est nullable et il faut préciser ? si on veut que ca le soit, même pour les classes
    ca sert pour que le compilateur puisse signaler plus facilement des références qui seront nulles et donc éviter des problèmes à l'exécution (faudrait demander à ceux qui l'ont essayé si réellement ca amène quelque chose)
    c'est un paramètre sur chaque projet, vous pouvez chercher c'est plutot vers le haut des paramètres, par défaut "référénce nullable" est "activé" et on peut le désactiver pour fonctionner comme avant

  4. #4
    Expert confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2009
    Messages
    2 032
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2009
    Messages : 2 032
    Points : 5 476
    Points
    5 476
    Par défaut
    Citation Envoyé par Pol63 Voir le message
    c'est un paramètre sur chaque projet, vous pouvez chercher c'est plutot vers le haut des paramètres, par défaut "référénce nullable" est "activé" et on peut le désactiver pour fonctionner comme avant
    Faut voir si c'est pour devenir le vieux grincheux réfractaire au changement, ou si vraiment il y a un intérêt. Pour l'instant je me sens vieux .

  5. #5
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 744
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 744
    Points : 5 434
    Points
    5 434
    Par défaut
    Citation Envoyé par Pol63 Voir le message
    Nullable (et donc le suffixe ?) ne sont autorisés que sur des types struct comme on peut le voir dans le code source de c#
    public struct Nullable<T> where T : struct=> donc les types par valeur mais pas les types par référence (class, string...)
    C'est justement pour cela que je pose la question.

    Car Nullable<Something> n'est pas autorisé (car Something est une classe et non un type struct).
    Jusque là, ça va.
    C'est logique.

    Mais Something? ne pose pas de problème !
    Pourquoi alors que Something n'est toujours pas un type struct ?

  6. #6
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 177
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 177
    Points : 25 125
    Points
    25 125
    Par défaut
    je pense que quand sur le projet nullable est activé le ? signifie alors au compilateur que null est autorisé, ca n'aurait donc plus rien à avoir avec nullable<>

  7. #7
    Membre chevronné
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 905
    Points : 1 923
    Points
    1 923
    Par défaut
    System.String est un type .Net, tandis que string est un mot-clé du langage C# qui référence ce type. De même, System.Nullable<T> est un type .Net, tandis que int? est un élément du langage C# qui référence Nullable<Int32>. Nullable<T> a été créé pour avoir l'équivalent de types valeurs nullables, alors qu'ils sont par nature non-nullables. Par nature les types références sont nullable, ce qui explique que Nullable<T> ne s'applique qu'aux type valeurs.

    string? est différent de int?. Tout d'abord string? référence bien le type System.String et non un nouveau type. Il s'agit d'une fonctionnalité du langage C# introduite dans sa version 8, appelée nullable reference types. Cette fonctionnalité est activée par défaut sur les projets .Net 6, alors qu'elle ne l'était pas sur les version précédentes, ce qui explique l'apparition soudaine de warnings sur du code classique. Elle constitue une réponse à la fameuse "billion-dollar mistake" de Tony Hoare : les références nullables. L'objectif est de réduire l'incidence de NullReferenceException dues au défaut de contrôle de nullité d'une référence avant de la déréférencer, en rendant explicitement nullables les types références, qui sont normalement implicitement nullables.

    Une référence déclarée string est censée être non-nulle, tandis que string? peut-être nulle. Le compilateur va examiner les chemins de code pour vérifier que ces conventions sont respectées. Par exemple, si une méthode prend un paramètre string?, puis le transmet à une méthode avec un paramètre string, le compilateur émettra un warning s'il n'y a pas une vérification de nullité au préalable. À noter que ce n'est pas une protection absolue et qu'il est toujours possible d'écrire du code qui peut contourner l'analyse du compilateur, comme précisé sur la page dédiée de la MSDN.

    Cela ressemble beaucoup au comportement des langages fonctionnels, qui n'utilisent généralement pas de références implicitement nullables, mais plutôt un type dédié, comme une union Maybe<T> ou Option<T>, qui aura pour valeur effective un Some T (il y a une valeur) ou bien None ou Nothing (il n'y a pas de valeur fournie). On gère ensuite généralement l'un ou l'autre cas par du pattern matching.

  8. #8
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 744
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 744
    Points : 5 434
    Points
    5 434
    Par défaut
    Merci Noxen mais la question ne porte pas sur un type String (qui ne pose aucun problème).
    La question porte sur un type Employee qui est une classe.

    Je voulais autoriser la valeur nulle pour dire qu'un employé n'avais potentiellement pas de manager (genre s'il est le patron).

    Au final la bonne syntaxe, celle qui fonctionne et ne génère aucun avertissement, consiste à ne pas déclarer la propriété nullable mais de spécifier que null est considéré comme normal.
    Ceci au moyen d'une valeur par défaut à null et d'un point d'exclamation derrière (le null-forgiving).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class Employee
        {
            public Guid Id { get; set; }
            public String FirstName { get; set; } = String.Empty;
            public String LastName { get; set; } = String.Empty;
     
            public Int32 Level { get; set; } = 0;
     
            public Nullable<Guid> ManagerId { get; set; }
            public virtual Employee Manager { get; set; } = null!;
     
            public virtual ICollection<Employee> Employees { get; } = new List<Employee>();
        }

  9. #9
    Membre chevronné
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 905
    Points : 1 923
    Points
    1 923
    Par défaut
    String est bien un type référence, comme Employee.

  10. #10
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 177
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 177
    Points : 25 125
    Points
    25 125
    Par défaut
    le résumé doit etre ca :

    il est interdit d'écrire Nullable<uneclasse> (dans tous les cas)
    par contre uneclasse? est autorisé si le projet gère la nullitude (par défaut depuis .net 6)
    et c'est à priori ce que tu cherches ... et en désactivant la gestion de null sur le projet une classe est automatiquement nullable comme ca l'était avant .net 6

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. LaTeX Error: Something's wrong--perhaps a missing \item.
    Par fasfousba dans le forum Débuter
    Réponses: 14
    Dernier message: 22/12/2009, 20h51
  2. Réponses: 4
    Dernier message: 30/10/2009, 16h04
  3. Something went wrong in PROD
    Par Javix dans le forum Ruby on Rails
    Réponses: 2
    Dernier message: 09/01/2009, 11h12
  4. Réponses: 14
    Dernier message: 14/09/2007, 17h28
  5. Réponses: 2
    Dernier message: 08/03/2007, 10h23

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo