[c#] Le direttive "using" dovrebbero essere all'interno o all'esterno dello spazio dei nomi?



3 Answers

Questa discussione ha già delle ottime risposte, ma sento di poter dare un po 'più di dettaglio con questa risposta aggiuntiva.

Innanzitutto, ricorda che una dichiarazione dello spazio dei nomi con punti, come:

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

è interamente equivalente a:

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

Se lo volessi, potresti using direttive su tutti questi livelli. (Ovviamente, vogliamo using s in un solo posto, ma sarebbe legale secondo la lingua.)

La regola per la risoluzione di quale tipo è implicito, può essere definita in modo approssimativo come segue: Prima cerca lo "scope" più interno per una corrispondenza, se non viene trovato nulla, esci di un livello al prossimo scope e cerca lì, e così via , fino a quando non viene trovata una corrispondenza. Se a un certo livello viene trovata più di una corrispondenza, se uno dei tipi proviene dall'assieme corrente, sceglierne uno ed emettere un avviso del compilatore. Altrimenti, arrendersi (errore in fase di compilazione).

Ora, diciamo esplicitamente cosa significa questo in un esempio concreto con le due principali convenzioni.

(1) Con gli usi esterni:

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;
    }
}

Nel caso precedente, per scoprire che tipo è Ambiguous , la ricerca va in questo ordine:

  1. Tipi annidati all'interno di C (inclusi tipi annidati ereditati)
  2. Tipi nello spazio dei nomi corrente MyCorp.TheProduct.SomeModule.Utilities
  3. Tipi nello spazio MyCorp.TheProduct.SomeModule nomi MyCorp.TheProduct.SomeModule
  4. Tipi in MyCorp.TheProduct
  5. Tipi in MyCorp
  6. Tipi nello spazio dei nomi null (lo spazio dei nomi globale)
  7. Tipi in System , System.Collections.Generic , System.Linq , MyCorp.TheProduct.OtherModule , MyCorp.TheProduct.OtherModule.Integration e ThirdParty

L'altra convenzione:

(2) Con le usanze all'interno:

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;
    }
}

Ora, cerca il tipo Ambiguous in questo ordine:

  1. Tipi annidati all'interno di C (inclusi tipi annidati ereditati)
  2. Tipi nello spazio dei nomi corrente MyCorp.TheProduct.SomeModule.Utilities
  3. Tipi in System , System.Collections.Generic , System.Linq , MyCorp.TheProduct , MyCorp.TheProduct.OtherModule , MyCorp.TheProduct.OtherModule.Integration e ThirdParty
  4. Tipi nello spazio MyCorp.TheProduct.SomeModule nomi MyCorp.TheProduct.SomeModule
  5. Tipi in MyCorp
  6. Tipi nello spazio dei nomi null (lo spazio dei nomi globale)

(Si noti che MyCorp.TheProduct faceva parte di "3." e non era quindi necessario tra "4." e "5.".)

Osservazioni conclusive

Non importa se si inseriscono gli usi all'interno o all'esterno della dichiarazione dello spazio dei nomi, c'è sempre la possibilità che qualcuno aggiunga successivamente un nuovo tipo con lo stesso nome a uno degli spazi dei nomi che hanno priorità più alta.

Inoltre, se uno spazio dei nomi annidato ha lo stesso nome di un tipo, può causare problemi.

È sempre pericoloso spostare gli usi da una posizione a un'altra perché la gerarchia della ricerca cambia e un altro tipo può essere trovato. Pertanto, scegli una convenzione e atteniti ad essa, in modo da non dover mai spostare gli usi.

I modelli di Visual Studio, per impostazione predefinita, inseriscono gli utilizzi al di fuori dello spazio dei nomi (ad esempio se si crea VS in una nuova classe in un nuovo file).

Un (piccolo) vantaggio di avere usi esterni è che è quindi possibile utilizzare le direttive using per un attributo globale, ad esempio [assembly: ComVisible(false)] invece di [assembly: System.Runtime.InteropServices.ComVisible(false)] .

Question

Ho eseguito StyleCop su un codice C # e continua a segnalare che le mie direttive di using dovrebbero essere all'interno dello spazio dei nomi.

Esiste un motivo tecnico per inserire le direttive di using all'interno anziché all'esterno dello spazio dei nomi?




C'è un problema con l'inserimento di istruzioni all'interno dello spazio dei nomi quando si desidera utilizzare alias. L'alias non beneficia delle dichiarazioni precedenti e deve essere pienamente qualificato.

Prendere in considerazione:

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

    class MyClass
    {
    }
}

contro:

using System;

namespace MyNamespace
{
    using MyAlias = DateTime;

    class MyClass
    {
    }
}

Questo può essere particolarmente pronunciato se si ha un alias prolisso come il seguente (che è il modo in cui ho trovato il problema):

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

Con l' using istruzioni all'interno dello spazio dei nomi, diventa improvvisamente:

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

Non carino.







È una pratica migliore se quelle impostazioni predefinite che utilizzano, ad esempio, i " riferimenti " utilizzati nella soluzione di origine, dovrebbero essere al di fuori degli spazi dei nomi e quelli che sono "nuovi riferimenti aggiunti" è una buona pratica, dovresti inserirli nello spazio dei nomi. Questo per distinguere quali riferimenti vengono aggiunti.




Related