В чем разница между этими двумя декларациями? - PullRequest
9 голосов
/ 05 июня 2009

Учитывая это объявление:

using System;
using System.Collections;
using System.Collections.Generic;

namespace AProject.Helpers
{
    public static class AClass
    {

и это объявление

namespace AProject.Helpers
{
    using System;
    using System.Collections;
    using System.Collections.Generic;

    public static class AClass
    {

Есть ли какая-то разница между ними? Или это просто разница в стилях кодирования?

Я всегда раньше объявлял свои классы как первые, но недавно заметил, что Microsoft использует второй .

Ответы [ 7 ]

26 голосов
/ 05 июня 2009

В последней версии директивы using применяются только в объявлении пространства имен.

В большинстве случаев у вас будет только одно объявление пространства имен:

// Using directives
...
namespace X
{
    // Maybe more using directives
    // Code
}
// End of file

Основное различие заключается в том, что в одном файле несколько пространств имен:

// Using directives
...
namespace X
{
    // Maybe more using directives
    // Code
}

namespace Y
{
    // Maybe more using directives
    // Code
}
// End of file

В этом случае директивы using в объявлении пространства имен X не влияют на код внутри объявления пространства имен Y, и наоборот.

Однако это не единственное отличие - есть тонкий случай, на который Эрик Липперт указывает , где он может повлиять на код даже с помощью одного объявления пространства имен. (В основном, если вы пишете using Foo; в объявлении пространства имен X, и есть пространство имен X.Foo, а также Foo, поведение меняется. Это можно исправить, используя псевдоним пространства имен, например, using global::Foo;, если вы действительно хотите. )

Лично я бы придерживался:

  • Одно объявление пространства имен на файл (и обычно один тип верхнего уровня на файл)
  • Использование директив вне декларации пространства имен
6 голосов
/ 05 июня 2009

Это делает директивы using локальными для этого пространства имен, что на практике не должно иметь значения, поскольку вы (надеюсь) не объявляете несколько типов в нескольких пространствах имен в одном исходном файле.

Подробности здесь .

2 голосов
/ 05 июня 2009

второе может быть неоднозначным;

Верхняя часть проясняет ваши следующие пространства имен:

  • System
  • System.Collections
  • System.Collections.Generic

В то время как второй сначала будет искать эти пространства имен:

  • AProject.Helpers.System
  • AProject.Helpers.System.Collections
  • AProject.Helpers.System.Collections.Generic

И вместо этого обращайтесь к ним, если они найдены ... Если нет, они оба будут ссылаться на одни и те же пространства имен.

Более безопасное переписывание второго будет:

namespace AProject.Helpers
{
    using global::System;
    using global::System.Collections;
    using global::System.Collections.Generic;
}
1 голос
/ 01 июля 2009

Другое важное различие между ними возникает при использовании LINQ-to-SQL и сгенерированных классов текстовых данных. Например, пример базы данных Northwind; изначально вы получаете:

  • Northwind.dbml
    • Northwind.dbml.layout
    • Northwind.designer.cs

Если вы теперь хотите расширить частичные классы, добавив свой собственный Northwind.cs, вы получите

  • Northwind.dbml
    • Northwind.dbml.layout
    • Northwind.designer.cs
    • Northwind.cs

Забавно , есть ошибка в генераторе кода (MSLinqToSQLGenerator) - это означает, что если директивы using находятся вне пространства имен (как будто они по умолчанию), он ломается - с сообщением:

The custom tool 'MSLinqToSQLGenerator' failed. Unspecified error

И файл Northwind.designer.cs удаляется. Нет больше контекста данных!

Однако, если вы переместите директивы using в пространство имен (и повторно запустите пользовательский инструмент - щелкните правой кнопкой мыши в обозревателе решений), он будет работать правильно.

Итак: это не языковая деталь - это просто ошибка в генераторе кода; но есть довольно большая разница между "работает правильно" и сгенерированным кодом удаляется ...

Обратите внимание, что вы также можете это исправить, просто назвав свой файл чем-то другим, например NorthwindExtras.cs.

Чумовая.

0 голосов
/ 05 июня 2009

И для процесса, на который указывает Арджан, считается плохой практикой объявлять использование внутри вашего пространства имен. Они могут быть неявно переопределены другим пространством имен.

0 голосов
/ 05 июня 2009

В первом примере объявления об использовании являются «глобальными» для всего файла. Во втором примере операторы using будут применяться только к коду, заключенному в блоке пространства имен.

Я думаю, что единственное время, когда это действительно имеет значение, - это если у вас есть более одного пространства имен в файле и вы хотите ограничить, какое пространство имен имеет доступ к каждому из них, используя объявление.

0 голосов
/ 05 июня 2009

Я полагаю, что может быть причина использовать второй вариант с точки зрения пуристов, так как он более ясно дает понять, какова область действия директив using.

...