Alors, voici une fonction générique que j'avais

int SomeArray(IEnumerable<int> array, int size) 
{
    int product = 1
    for (var i = 0; i < size; i++)
    {
        product *= array[i];
    }
    return product
}

Visual Studio ou ReSharper, je ne sais pas lequel, a suggéré de changer array[i] pour énumérer en tant que tableau en changeant la fonction en

var enumerable = array as int[] ?? array.ToArray();
for (var i = 0; i < size; i++)
{
    product *= enumerable[i];
}

Le problème que je vois est que le passé dans array pourrait être nul et Visual Studio met en garde contre un éventuel System.NullReferenceException lancé.

La vraie question est que l'idée de l'opérateur de fusion nul est que si l'opérande de gauche est nul, l'opérande de droite sera utilisé.

Si je fais var enumerable = array as int[] ?? array.ToArray() ?? new int[size]; Le new int[size] est marqué comme n'étant pas nécessaire car selon Visual Studio, les éléments de gauche ne pourraient jamais être nuls. Quand je peux clairement forcer le tableau passé à être nul.

Alors qu'est-ce que je n'obtiens pas ici?

0
Samuel 31 mars 2017 à 23:20

2 réponses

Meilleure réponse

Cette expression

var enumerable = array as int[] ?? array.ToArray();

Ne peut jamais être nul (selon Resharper), car si array est nul - il lèvera une exception, et ToArray est connu par Resharper pour ne jamais retourner null (il existe une base de données spéciale de méthodes que Resharper sait ne peut pas return null, et vous pouvez marquer le vôtre avec l'attribut NotNull).

Si vous êtes intéressé par cette "base de données" Resharper (appelée annotations externes, qui n'est qu'un fichier xml), voici la source où vous pouvez voir:

 <member
    name="M:System.Linq.Enumerable.ToArray``1(System.Collections.Generic.IEnumerable{``0})">
     <parameter name="source">
       <attribute ctor="M:JetBrains.Annotations.NotNullAttribute.#ctor" />
     </parameter>
     <attribute ctor="M:JetBrains.Annotations.NotNullAttribute.#ctor" />          
</member>

Où vous pouvez voir que ToArray() est marqué avec l'attribut NotNull. Pour cette raison, Resharper est sûr que ToArray() ne peut pas retourner null (alors qu'en théorie, il le pourrait).

Si vous souhaitez utiliser votre expression, vous devez vérifier le tableau pour null, comme ceci (si vous pouvez utiliser C # 6):

var enumerable = array as int[] ?? array?.ToArray() ?? new int[size];

Ou ca:

var enumerable = array as int[] ?? (array != null ? array.ToArray() : new int[size]);
2
Evk 31 mars 2017 à 20:47

Si array était null alors cette ligne de code appellerait array.ToArray sur cette valeur null, et elle lèvera un argument d'exception null.

ToArray ne retournera jamais une valeur null (même si une valeur null est fournie), c'est pourquoi votre constructeur de tableau ne peut jamais être appelé.

1
Servy 31 mars 2017 à 20:30