[C#] Les directives 'using' devraient-elles être à l'intérieur ou à l'extérieur de l'espace de noms?



Answers

Ce fil a déjà quelques bonnes réponses, mais je pense que je peux apporter un peu plus de détails avec cette réponse supplémentaire.

D'abord, rappelez-vous qu'une déclaration d'espace de noms avec des points, comme:

namespace MyCorp.TheProduct.SomeModule.Utilities
{
    ...
}

est entièrement équivalent à:

namespace MyCorp
{
    namespace TheProduct
    {
        namespace SomeModule
        {
            namespace Utilities
            {
                ...
            }
        }
    }
}

Si vous le souhaitez, vous pouvez using directives à tous ces niveaux. (Bien sûr, nous voulons using s dans un seul endroit, mais ce serait légal selon la langue.)

La règle pour résoudre quel type est implicite, peut être énoncée de manière lâche comme ceci: Cherchez d'abord la "portée" la plus interne pour une correspondance, si rien ne s'y trouve, passez d'un niveau à l'étendue suivante et y cherchez, et ainsi de suite , jusqu'à ce qu'une correspondance soit trouvée. Si, à un certain niveau, plus d'une correspondance est trouvée, si l'un des types provient de l'assemblage actuel, choisissez celui-là et lancez un avertissement du compilateur. Sinon, abandonnez (erreur de compilation).

Maintenant, soyons explicites sur ce que cela signifie dans un exemple concret avec les deux conventions majeures.

(1) Avec des utilisations dehors:

using System;
using System.Collections.Generic;
using System.Linq;
//using MyCorp.TheProduct;  <-- uncommenting this would change nothing
using MyCorp.TheProduct.OtherModule;
using MyCorp.TheProduct.OtherModule.Integration;
using ThirdParty;

namespace MyCorp.TheProduct.SomeModule.Utilities
{
    class C
    {
        Ambiguous a;
    }
}

Dans le cas ci-dessus, pour savoir quel type est Ambiguous , la recherche s'effectue dans cet ordre:

  1. Types imbriqués à l'intérieur de C (y compris les types imbriqués hérités)
  2. Types dans l'espace de noms actuel MyCorp.TheProduct.SomeModule.Utilities
  3. Types dans l'espace de noms MyCorp.TheProduct.SomeModule
  4. Types dans MyCorp.TheProduct
  5. Types dans MyCorp
  6. Types dans l'espace de noms nul (l'espace de noms global)
  7. Types dans System , System.Collections.Generic , System.Linq , MyCorp.TheProduct.OtherModule , MyCorp.TheProduct.OtherModule.Integration et ThirdParty

L'autre convention:

(2) Avec des utilisations à l'intérieur:

namespace MyCorp.TheProduct.SomeModule.Utilities
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using MyCorp.TheProduct;                           // MyCorp can be left out; this using is NOT redundant
    using MyCorp.TheProduct.OtherModule;               // MyCorp.TheProduct can be left out
    using MyCorp.TheProduct.OtherModule.Integration;   // MyCorp.TheProduct can be left out
    using ThirdParty;

    class C
    {
        Ambiguous a;
    }
}

Maintenant, recherchez le type Ambiguous dans cet ordre:

  1. Types imbriqués à l'intérieur de C (y compris les types imbriqués hérités)
  2. Types dans l'espace de noms actuel MyCorp.TheProduct.SomeModule.Utilities
  3. Types dans System , System.Collections.Generic , System.Linq , MyCorp.TheProduct , MyCorp.TheProduct.OtherModule , MyCorp.TheProduct.OtherModule.Integration et ThirdParty
  4. Types dans l'espace de noms MyCorp.TheProduct.SomeModule
  5. Types dans MyCorp
  6. Types dans l'espace de noms nul (l'espace de noms global)

(Notez que MyCorp.TheProduct faisait partie de "3." et n'était donc pas nécessaire entre "4." et "5.".)

Remarques de conclusion

Peu importe si vous placez les utilisations à l'intérieur ou à l'extérieur de la déclaration d'espace de noms, il est toujours possible que quelqu'un ajoute un nouveau type avec un nom identique à l'un des espaces de noms ayant une priorité plus élevée.

En outre, si un espace de noms imbriqué a le même nom qu'un type, il peut entraîner des problèmes.

Il est toujours dangereux de déplacer les données d'un emplacement à un autre car la hiérarchie de recherche change et un autre type peut être trouvé. Par conséquent, choisissez une convention et tenez-vous-y, de sorte que vous ne deviez jamais déplacer des utilisations.

Par défaut, les modèles de Visual Studio placent les utilisations en dehors de l'espace de noms (par exemple, si VS fait générer une nouvelle classe dans un nouveau fichier).

Un (minuscule) avantage d'avoir des utilisations à l' extérieur est que vous pouvez ensuite utiliser les directives using pour un attribut global, par exemple [assembly: ComVisible(false)] au lieu de [assembly: System.Runtime.InteropServices.ComVisible(false)] .

Question

J'ai exécuté StyleCop sur du code C #, et il continue de signaler que mes directives using devraient être dans l'espace de noms.

Y a-t-il une raison technique pour mettre les directives using intérieur et non à l'extérieur de l'espace de noms?







Il y a un problème avec le fait de placer des instructions à l'intérieur de l'espace de noms lorsque vous souhaitez utiliser des alias. L'alias ne bénéficie pas des instructions d' using antérieures et doit être pleinement qualifié.

Considérer:

namespace MyNamespace
{
    using System;
    using MyAlias = System.DateTime;

    class MyClass
    {
    }
}

contre:

using System;

namespace MyNamespace
{
    using MyAlias = DateTime;

    class MyClass
    {
    }
}

Cela peut être particulièrement prononcé si vous avez un alias à long terme tel que celui-ci (c'est ainsi que j'ai trouvé le problème):

using MyAlias = Tuple<Expression<Func<DateTime, object>>, Expression<Func<TimeSpan, object>>>;

En using instructions à l'intérieur de l'espace de noms, il devient soudain:

using MyAlias = System.Tuple<System.Linq.Expressions.Expression<System.Func<System.DateTime, object>>, System.Linq.Expressions.Expression<System.Func<System.TimeSpan, object>>>;

Pas beau.




C'est une meilleure pratique si les " références " utilisées par défaut dans votre solution source doivent être en dehors des espaces de noms et celles qui sont "nouvelle référence ajoutée" est une bonne pratique à mettre dans l'espace de noms. C'est pour distinguer quelles références sont ajoutées.




Links