41 votes

Comparer un générique à null qui pourrait être une valeur ou un type de référence?

public void DoFoo<T>(T foo) where T : ISomeInterface<T>
{
    //possible compare of value type with 'null'.
    if (foo == null) throw new ArgumentNullException("foo");
}

Je suis volontairement la seule vérification par rapport à null car je ne veux pas restreindre ValueType d'être égal à son default(T). Mon code compile et fonctionne très bien de cette façon (ReSharper se plaint, mais pas CodeAnalysis). Si je ne me demande:

  • Est-il plus standard de la manière de gérer cette situation?
  • Est-il une chance d'un problème arrising à partir de cela?
  • Ce qui se passe réellement sous le capot quand je fais un appel et passer dans un type de valeur?

54voto

Eric Lippert Points 300275

Je suis volontairement la seule vérification à l'encontre null parce que je ne veux pas restreindre un ValueType d'être égal à son default(T)

C'est une bonne idée, mais ne vous inquiétez pas, vous êtes déjà couvert. Il n'est pas légal de comparer un T contre default(T) l'aide == dans la première place; résolution de surcharge ne sera pas trouver une meilleure == de l'opérateur.

Bien sûr, on pourrait faire la comparaison avec d' .Equals mais vous courez le risque de se planter si le récepteur est nulle, ce qui est précisément ce que vous essayez d'éviter.

Est-il plus standard de la manière de gérer cette situation?

Pas de. Comparer à la valeur null est la bonne chose à faire ici.

Comme la spécification C# est dit dans l'article 7.10.6: "L' x == null construction est permise même si T pourrait représenter un type de valeur, et le résultat est simplement défini à false lorsque T est un type valeur."

Est-il une chance d'un problème arrising à partir de cela?

Assurez-vous. Tout simplement parce que le code compile ne signifie pas qu'il a la sémantique que vous le souhaitez. Écrire des tests.

Ce qui se passe réellement sous le capot quand je fais un appel et passer dans un type de valeur?

La question est ambiguë. Permettez-moi de reformuler en deux questions:

Ce qui se passe réellement sous le capot quand je fais un appel à la méthode générique avec un argument de type qui est un non nullable le type de valeur?

La gigue compile la méthode pour le premier appel avec cette construction. Quand la gigue détecte la valeur null est à vérifier, qu'il remplace par "faux" parce qu'il sache qu'il n'accepte pas les valeurs null type de valeur ne sera jamais égale à null.

Ce qui se passe réellement sous le capot quand je fais un appel à la méthode générique avec un argument de type qui est un type de référence, mais d'un argument qui est un type struct? Par exemple:

interface IFoo : ISomeInterface<IFoo> {}
struct SFoo : IFoo { whatever }
...
DoFooInternal<IFoo>(new SFoo());

Dans ce cas, la gigue ne peut pas éluder le nul de vérifier et le site d'appel ne peut pas éviter la boxe. Le SFoo instance va être mis en boîte, et la référence à la boîte SFoo sera vérifiée pour voir si elle est nulle.

11voto

Nuffin Points 3045

Non, il n'y aura pas de problèmes, mais si vous souhaitez que l'avertissement disparaisse, vous pouvez utiliser les éléments suivants:

 public void DoFoo<T>(T foo) where T : ISomeInterface<T>
{
    if (ReferenceEquals(foo, null)) throw new ArgumentNullException("foo");
}
 

Sinon, vous pouvez faire quelque chose comme ça:

 // when calling this with an actual T parameter, you have to either specify the type
// explicitly or cast the parameter to T?.
public void DoFoo<T>(T? foo) where T : struct, ISomeInterface<T>
{
    if (foo == null)
    {
        // throw...
    }

    DoFooInternal(foo.Value);
}

public void DoFoo<T>(T foo) where T : class, ISomeInterface<T>
{
    if (foo == null)
    {
        // throw...
    }

    DoFooInternal(foo); 
}

private void DoFooInternal<T>(T foo) where T : ISomeInterface<T>
{
    // actual implementation
}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X