2015-10-24 2 views
1

Compte tenu d'une classe avec un opérateur de conversion implicite à un Guid:conversion implicite à struct exécute contre Nullable <struct>

class MyId 
{ 
    private readonly Guid innerGuid; 

    public MyId(Guid innerGuid) 
    { 
     this.innerGuid = innerGuid; 
    } 

    public static implicit operator Guid(MyId id) 
    { 
     return id.innerGuid; 
    } 
} 

Lors de l'attribution à un Nullable<Guid>:

static void Main(string[] args) 
    { 
     MyId someId = null; 
     Guid? optionalId = someId; 
     Console.WriteLine("optionalId = " + (optionalId.HasValue ? optionalId.Value.ToString() : "NULL")); 
    } 

je me attends la référence null à se propager simplement de someId à optionalId. c'est à dire. obtenir la sortie de la console:

optionalId = NULL

Cependant, le compilateur semble avoir la priorité sur intérieure de type Guid du Nullable, et il tente d'exécuter la conversion implicite, ce qui jette un NRE comme id le paramètre est évidemment nul.

Est-ce un bug ou un design?

Il peut être fixé avec un opérateur coalescent null et la valeur null explicite:

static void Main(string[] args) 
    { 
     MyId someId = null; 
     Guid? optionalId = someId ?? (Guid?) null; 
     Console.WriteLine("optionalId = " + (optionalId.HasValue ? optionalId.Value.ToString() : "NULL")); 
    } 

Mais cela semble très bizarre. Resharper l'efface même, ce qui implique qu'il est inutile et indique:

'??' l'opérande droit est toujours nul

+0

Avez-vous essayé 'optionalId = (MyId) null' voir si il lance ou non. Actuellement, null cast vers guid n'invoque évidemment pas votre opérateur implicite qui prend MyId –

+0

IMHO, ce que vous décrivez est un comportement correct. Il exécute correctement l'opérateur implicite. Vous pouvez le réparer en ajoutant un opérateur implicite à un Nullable et en utilisant l'opérateur de coalescence null ?? dans cette fonction. Alternativement, changez l'opérateur implicite que vous avez pour retourner un Nullable . Il devrait probablement fonctionner pour Guid et Nullable ; – GreatAndPowerfulOz

+0

@ Gread.And.Powerful.Oz Oui, l'ajout d'un opérateur implicite pour la surcharge 'Nullable ' corrige ce cas. Malheureusement mon cas réel n'est pas si simple (une classe de base générique 'Identity ', qui peut utiliser Guid, int, string, etc. Ajouter une conversion implicite à 'Nullable ' signifie que je dois donner 'TId' une contrainte de structure, ce qui signifie que je ne peux plus utiliser l'identité ) – Tyson

Répondre

1

parce que vous avez une variable de type MyId, pas de Guid? et vous attribuez cette variable à un Guid? et le type MyId a un opérateur de conversion IMPLICIT. Si vous l'avez fait EXPLICIT alors le compilateur se plaindrait probablement de l'absence de conversion. Que voulez-vous exactement arriver en assignant une instance de classe Foo nulle à un Guid? variable? Est-ce que vous vous attendez vraiment à ce que cela soit significatif? -