Должны ли директивы using находиться внутри или вне пространства имен?

Я запускал StyleCop над некоторым кодом C #, и он продолжает сообщать, что мои директивы using должны быть внутри пространство имен.

Есть ли техническая причина для размещения директив using внутри, а не за пределами пространства имен?


person benPearce    schedule 24.09.2008    source источник
comment
Иногда имеет значение, где вы помещаете использование: stackoverflow.com/ вопросы / 292535 / linq-to-sql-designer-bug   -  person gius    schedule 12.12.2008
comment
Просто для справки, есть последствия, выходящие за рамки вопроса о нескольких классах в файле, поэтому, если вы новичок в этом вопросе, продолжайте читать.   -  person Charlie    schedule 22.01.2010
comment
@ user-12506 - это не очень хорошо работает в средней и большой команде разработчиков, где требуется некоторый уровень согласованности кода. И, как отмечалось ранее, если вы не понимаете различных макетов, вы можете обнаружить крайние случаи, которые не работают так, как вы ожидаете.   -  person benPearce    schedule 04.02.2014
comment
Терминология: это не using утверждения; это using директивы. С другой стороны, оператор using - это языковая структура, которая встречается вместе с другими операторами внутри тела метода и т. Д. Например, using (var e = s.GetEnumerator()) { /* ... */ } - это оператор, который примерно такой же, как var e = s.GetEnumerator(); try { /* ... */ } finally { if (e != null) { e.Dispose(); } }.   -  person Jeppe Stig Nielsen    schedule 12.04.2017
comment
Если об этом еще никто не упоминал, на самом деле Microsoft тоже рекомендует помещать операторы using внутри объявлений namespace в их внутренние правила кодирования   -  person user1451111    schedule 27.07.2018


Ответы (12)


На самом деле между ними есть (тонкая) разница. Представьте, что у вас есть следующий код в File1.cs:

// File1.cs
using System;
namespace Outer.Inner
{
    class Foo
    {
        static void Bar()
        {
            double d = Math.PI;
        }
    }
}

Теперь представьте, что кто-то добавляет в проект еще один файл (File2.cs), который выглядит следующим образом:

// File2.cs
namespace Outer
{
    class Math
    {
    }
}

Компилятор ищет Outer перед тем, как смотреть на эти using директивы за пределами пространства имен, поэтому он находит Outer.Math вместо System.Math. К сожалению (или, возможно, к счастью?), Outer.Math не имеет участника PI, поэтому File1 теперь не работает.

Это изменится, если вы поместите using в объявление пространства имен, как показано ниже:

// File1b.cs
namespace Outer.Inner
{
    using System;
    class Foo
    {
        static void Bar()
        {
            double d = Math.PI;
        }
    }
}

Теперь компилятор ищет System перед поиском Outer, находит System.Math, и все в порядке.

Некоторые могут возразить, что Math может быть плохим именем для пользовательского класса, поскольку он уже есть в System; Дело здесь как раз в том, что есть разница, и она влияет на ремонтопригодность вашего кода.

Также интересно отметить, что происходит, если Foo находится в пространстве имен Outer, а не Outer.Inner. В этом случае добавление Outer.Math в File2 приводит к разрыву File1 независимо от того, где находится using. Это означает, что компилятор просматривает самое внутреннее охватывающее пространство имен, прежде чем он посмотрит любую директиву using.

person Charlie    schedule 30.09.2008

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

Во-первых, помните, что объявление пространства имен с точками, например:

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

полностью эквивалентен:

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

Если хотите, вы можете разместить using директивы на всех этих уровнях. (Конечно, мы хотим иметь usings только в одном месте, но это было бы законно в зависимости от языка.)

Правило определения того, какой тип подразумевается, можно в общих чертах сформулировать следующим образом: Сначала выполните поиск совпадения в самой внутренней "области", если там ничего не найдено, перейдите на один уровень в следующую область и выполните поиск там, и так далее, пока не будет найдено совпадение. Если на каком-то уровне найдено более одного совпадения, если один из типов взят из текущей сборки, выберите его и выдайте предупреждение компилятору. В противном случае откажитесь (ошибка времени компиляции).

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

(1) При использовании вне дома:

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

В приведенном выше случае, чтобы узнать, что это за тип Ambiguous, поиск выполняется в следующем порядке:

  1. Вложенные типы внутри C (включая унаследованные вложенные типы)
  2. Типы в текущем пространстве имен MyCorp.TheProduct.SomeModule.Utilities
  3. Типы в пространстве имен MyCorp.TheProduct.SomeModule
  4. Типы в MyCorp.TheProduct
  5. Типы в MyCorp
  6. Типы в пространстве имен null (глобальное пространство имен)
  7. Типы в System, System.Collections.Generic, System.Linq, MyCorp.TheProduct.OtherModule, MyCorp.TheProduct.OtherModule.Integration и ThirdParty

Другое соглашение:

(2) Использование внутри:

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

Теперь поиск типа Ambiguous идет в следующем порядке:

  1. Вложенные типы внутри C (включая унаследованные вложенные типы)
  2. Типы в текущем пространстве имен MyCorp.TheProduct.SomeModule.Utilities
  3. Типы в System, System.Collections.Generic, System.Linq, MyCorp.TheProduct, MyCorp.TheProduct.OtherModule, MyCorp.TheProduct.OtherModule.Integration и ThirdParty
  4. Типы в пространстве имен MyCorp.TheProduct.SomeModule
  5. Типы в MyCorp
  6. Типы в пространстве имен null (глобальное пространство имен)

(Обратите внимание, что MyCorp.TheProduct был частью «3» и поэтому не нужен между «4» и «5».)

Заключительные замечания

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

Кроме того, если вложенное пространство имен имеет то же имя, что и тип, это может вызвать проблемы.

Всегда опасно перемещать использование из одного места в другое, потому что иерархия поиска изменяется, и может быть найден другой тип. Поэтому выберите одно соглашение и придерживайтесь его, чтобы вам никогда не пришлось менять использование.

Шаблоны Visual Studio по умолчанию помещают использование вне пространства имен (например, если вы заставляете VS генерировать новый класс в новом файле).

Одно (крошечное) преимущество использования вне заключается в том, что вы можете затем использовать директивы using для глобального атрибута, например [assembly: ComVisible(false)] вместо [assembly: System.Runtime.InteropServices.ComVisible(false)].

person Jeppe Stig Nielsen    schedule 18.04.2013
comment
Просто был случай, когда в унаследованной мной библиотеке классов были классы в глобальном / нулевом пространстве имен. Одно из имен классов было таким же, как имя класса внутри пространства имен, которое я использовал. 'Using' были вне определения пространства имен. Я не мог понять, почему он всегда выбирал определение глобального класса. Случайно поместил пространство имен снаружи - и оно подобрало нужный мне класс. Ваш ответ объясняет почему. При внешнем пространстве имен null / globals выбираются последними. Для меня это правильное / ожидаемое поведение. - person Paul Evans; 23.03.2021
comment
@PaulEvans Ваш случай также является примером того, почему нельзя ничего помещать в глобальное пространство имен, особенно ничего публичного. Библиотека, которую вы использовали, нарушила это. - person Jeppe Stig Nielsen; 24.03.2021

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

using ThisNamespace.IsImported.InAllNamespaces.Here;

namespace Namespace1
{ 
   using ThisNamespace.IsImported.InNamespace1.AndNamespace2;

   namespace Namespace2
   { 
      using ThisNamespace.IsImported.InJustNamespace2;
   }       
}

namespace Namespace3
{ 
   using ThisNamespace.IsImported.InJustNamespace3;
}
person Mark Cidade    schedule 24.09.2008
comment
пространства имен обеспечивают логическое разделение, а не физическое (файловое). - person Jowen; 26.09.2013
comment
Не совсем верно, что нет разницы; Директивы using в namespace блоках могут ссылаться на относительные пространства имен на основе включающего блока namespace. - person O. R. Mapper; 09.02.2014
comment
Да, я знаю. мы установили это в принятом ответе на этот вопрос пять лет назад. - person Mark Cidade; 11.02.2014

Согласно Hanselman - Using Directive and Assembly Loading ... и другим подобным статьям технически нет разницы.

Я предпочитаю размещать их вне пространств имен.

person Quintin Robinson    schedule 24.09.2008
comment
@Chris M: эээ ... ссылка, размещенная в ответе, указывает на отсутствие преимущества in vs. out, фактически демонстрируя пример, который фальсифицирует утверждение, сделанное в опубликованной вами ссылке ... - person johnny; 19.08.2011
comment
Да, я не полностью прочитал ветку, но согласился, когда MVP сказали, что это правильно. Парень опровергает это, объясняет и показывает свой код ниже ... IL, который генерирует компилятор C #, одинаков в любом случае. Фактически компилятор C # не генерирует ничего, соответствующего каждой директиве using. Директивы using - это чисто C # ism, и они не имеют никакого значения для самой .NET. (Неправильно для операторов using, но это совсем другое дело.) groups.google. com / group / wpf-administles / msg / 781738deb0a15c46. - person Chris McKee; 25.08.2011
comment
Пожалуйста, включите краткое содержание ссылки. Когда ссылка не работает (потому что это произойдет, если будет достаточно времени), внезапно ответ с 32 положительными голосами будет стоить только My style is to put them outside the namespaces. - почти не ответ вообще. - person ANeves thinks SE is evil; 22.10.2012
comment
Заявление здесь просто неверно ... есть техническая разница, и ваша собственная цитата говорит об этом ... на самом деле, в этом все дело. Пожалуйста, удалите этот ошибочный ответ ... есть гораздо лучшие и точные. - person Jim Balter; 17.04.2016
comment
OP заявил, что технически нет разницы в их ответе, и они верны - с технической точки зрения нет разницы. Утверждать, что это ошибочный ответ, совершенно неверно - person Martin; 02.07.2021

Согласно документации StyleCop:

SA1200: UsingDirectivesMustBePlacedWithinNamespace

Причина Директива using C # размещена за пределами элемента пространства имен.

Описание правила Нарушение этого правила происходит, когда директива using или директива using-alias размещается за пределами элемента пространства имен, если файл не содержит никаких элементов пространства имен.

Например, следующий код приведет к двум нарушениям этого правила.

using System;
using Guid = System.Guid;

namespace Microsoft.Sample
{
    public class Program
    {
    }
}

Однако следующий код не приведет к каким-либо нарушениям этого правила:

namespace Microsoft.Sample
{
    using System;
    using Guid = System.Guid;

    public class Program
    {
    }
}

Этот код будет компилироваться чисто, без ошибок компилятора. Однако неясно, какая версия типа Guid выделяется. Если директива using перемещается внутрь пространства имен, как показано ниже, произойдет ошибка компилятора:

namespace Microsoft.Sample
{
    using Guid = System.Guid;
    public class Guid
    {
        public Guid(string s)
        {
        }
    }

    public class Program
    {
        public static void Main(string[] args)
        {
            Guid g = new Guid("hello");
        }
    }
}

Код не работает из-за следующей ошибки компилятора, найденной в строке, содержащей Guid g = new Guid("hello");

CS0576: Пространство имен Microsoft.Sample содержит определение, конфликтующее с псевдонимом Guid

Код создает псевдоним типа System.Guid с именем Guid, а также создает собственный тип с именем Guid с соответствующим интерфейсом конструктора. Позже код создает экземпляр типа Guid. Чтобы создать этот экземпляр, компилятор должен выбрать между двумя разными определениями Guid. Когда директива using-alias размещается за пределами элемента пространства имен, компилятор выбирает локальное определение Guid, определенное в локальном пространстве имен, и полностью игнорирует директиву using-alias, определенную вне пространства имен. Это, к сожалению, не очевидно при чтении кода.

Однако, когда директива using-alias расположена в пространстве имен, компилятор должен выбирать между двумя разными конфликтующими типами Guid, которые определены в одном пространстве имен. Оба эти типа предоставляют соответствующий конструктор. Компилятор не может принять решение, поэтому он отмечает ошибку компилятора.

Размещение директивы using-alias за пределами пространства имен - плохая практика, потому что это может привести к путанице в таких ситуациях, как эта, когда неочевидно, какая версия типа фактически используется. Это потенциально может привести к ошибке, которую будет сложно диагностировать.

Размещение директив using-alias в элементе пространства имен устраняет это как источник ошибок.

  1. Несколько пространств имен

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

Важно отметить, что когда код был написан с использованием директив, размещенных за пределами пространства имен, следует проявлять осторожность при перемещении этих директив в пространстве имен, чтобы гарантировать, что это не изменит семантику кода. Как объяснялось выше, размещение директив using-alias в элементе пространства имен позволяет компилятору выбирать между конфликтующими типами способами, которые не будут происходить, если директивы размещены за пределами пространства имен.

Как исправить нарушения Чтобы исправить нарушение этого правила, переместите все директивы using и директивы using-alias в элемент пространства имен.

person JaredCacurak    schedule 14.09.2009
comment
@Jared - как я отметил в своем ответе, мой предпочтительный обходной путь / решение - всегда иметь только один класс для каждого файла. Я думаю, что это довольно распространенная конвенция. - person benPearce; 15.09.2009
comment
В самом деле, это тоже правило StyleCop! SA1402: документ C # может содержать только один класс на корневом уровне, если все классы не являются частичными и относятся к одному типу. Продемонстрировать одно правило, нарушив другое, просто капает с неправильным соусом. - person Task; 05.03.2010
comment
Проголосовали за то, чтобы быть первым ответом, который действительно освещает это с точки зрения StyleCop. Лично мне нравится визуальное восприятие usings вне пространства имен. Внутренний usings мне кажется таким уродливым. :) - person nawfal; 06.06.2015
comment
Наконец-то хороший ответ на вопрос. И комментарий benPearce не имеет значения ... это не имеет ничего общего с количеством классов в файле. - person Jim Balter; 17.04.2016

Если вы хотите использовать псевдонимы, возникает проблема с размещением операторов using внутри пространства имен. Псевдоним не пользуется преимуществами предыдущих операторов using и должен быть полностью определен.

Рассмотреть возможность:

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

    class MyClass
    {
    }
}

против:

using System;

namespace MyNamespace
{
    using MyAlias = DateTime;

    class MyClass
    {
    }
}

Это может быть особенно ярко выражено, если у вас есть длинный псевдоним, например следующий (именно так я обнаружил проблему):

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

С операторами using внутри пространства имен он внезапно становится:

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

Не очень.

person Neo    schedule 10.10.2012
comment
Вашему class нужно имя (идентификатор). У вас не может быть директивы using внутри класса, как вы указываете. Он должен находиться на уровне пространства имен, например, вне самого внешнего namespace или только внутри самого внутреннего namespace (но не внутри класса / интерфейса / и т. Д.). - person Jeppe Stig Nielsen; 23.03.2016
comment
@JeppeStigNielsen Спасибо. Я ошибочно разместил директивы using. Я отредактировал его так, как задумал. Спасибо, что указали. Однако рассуждения все те же. - person Neo; 23.03.2016

Одна морщина, с которой я столкнулся (которая не рассматривается в других ответах):

Предположим, у вас есть эти пространства имен:

  • Что-то другое
  • Родитель, что-то, другое

Когда вы используете using Something.Other вне namespace Parent, это относится к первому (Something.Other).

Однако, если вы используете его внутри объявления этого пространства имен, он будет ссылаться на второе (Parent.Something.Other)!

Есть простое решение: добавить префикс "global::": документы

namespace Parent
{
   using global::Something.Other;
   // etc
}
person Hans Kesting    schedule 05.06.2019
comment
Хорошая точка зрения! Я столкнулся с проблемой, связанной с работой с RazorGenerator. К сожалению, похоже, что он не понимает 'global ::' и преобразует его в 'using global;' :( Жаль, что я не могу выбрать, нужно ли сгенерировать using внутри или вне пространства имен ... - person Alexander; 05.01.2021

Как сказал Джеппе Стиг Нильсен , в этой ветке уже есть отличные ответы, но я подумал, что об этой довольно очевидной тонкости тоже стоит упомянуть.

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

Следующий пример работает, потому что типы Foo и Bar находятся в одном и том же глобальном пространстве имен, Outer.

Предположим, файл кода Foo.cs:

namespace Outer.Inner
{
    class Foo { }
}

И Bar.cs:

namespace Outer
{
    using Outer.Inner;

    class Bar
    {
        public Foo foo;
    }
}

Это может опустить внешнее пространство имен в директиве using, для краткости:

namespace Outer
{
    using Inner;

    class Bar
    {
        public Foo foo;
    }
}
person Biscuits    schedule 17.09.2016
comment
Это правда, что вы можете опустить внешнее пространство имен, но это не значит, что вы должны это делать. Для меня это еще один аргумент относительно того, почему директивы using (кроме псевдонимов, как в ответе @ Neo) должны выходить за пределы пространства имен, чтобы принудительно использовать полностью определенные имена пространств имен. - person Keith Robertson; 03.11.2016

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

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

//file1.cs
namespace Foo
{
    class Foo
    {
    }
}

//file2.cs
namespace ConsoleApp3
{
    using Foo;
    class Program
    {
        static void Main(string[] args)
        {
            //This will allow you to use the class
            Foo test = new Foo();
        }
    }
}

//file2.cs
using Foo; //Unused and redundant    
namespace Bar
{
    class Bar
    {
        Bar()
        {
            Foo.Foo test = new Foo.Foo();
            Foo test = new Foo(); //will give you an error that a namespace is being used like a class.
        }
    }
}
person Ben Gardner    schedule 24.08.2018

Технические причины обсуждаются в ответах, и я думаю, что в конечном итоге дело доходит до личных предпочтений, поскольку разница не такая большая и есть компромиссы для них обоих. В шаблоне Visual Studio по умолчанию для создания .cs файлов используются директивы using вне пространств имен, например.

Можно настроить stylecop для проверки using директив вне пространств имен, добавив stylecop.json файл в корень файла проекта со следующим:

{
  "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
    "orderingRules": {
      "usingDirectivesPlacement": "outsideNamespace"
    }
  }
}

Вы можете создать этот файл конфигурации на уровне решения и добавить его в свои проекты как «Существующий файл ссылок», чтобы также использовать конфигурацию для всех ваших проектов.

person sotn    schedule 03.06.2018

Ссылаясь на внутренние правила Microsoft, имейте в виду, что они написаны кем-то, кто, вероятно, имеет менее десяти лет опыта программирования. Другими словами, они, вероятно, основаны не более чем на личных предпочтениях. Особенно в таких новинках, как C #.

Как правило, внешние директивы using (например, пространства имен System и Microsoft) следует размещать вне директивы namespace. Это значения по умолчанию, которые следует применять во всех случаях, если не указано иное. Это должно включать любые внутренние библиотеки вашей организации, которые не являются частью текущего проекта, или директивы using, которые ссылаются на другие первичные пространства имен в том же проекте. Любые using директивы, которые ссылаются на другие модули в текущем проекте и пространстве имен, должны быть помещены внутри директивы namespace. Это выполняет две конкретные функции:

  • Он обеспечивает визуальное различие между локальными модулями и «другими» модулями, то есть всем остальным.
  • Он ограничивает применение локальных директив предпочтительно над глобальными директивами.

Последняя причина существенна. Это означает, что сложнее ввести неоднозначную справочную проблему, которая может быть вызвана изменением, не более значительным, чем рефакторинг кода. То есть вы перемещаете метод из одного файла в другой, и внезапно обнаруживается ошибка, которой раньше не было. В просторечии «гейзенбаг» - исторически невероятно трудно выследить.

Еще более общее правило, которому следует следовать. Если вы видите что-то присущее языку, которое кажется бесполезным вариантом, предположите, что это НЕ. На самом деле, чем сложнее понять, почему существует такая возможность, тем важнее ее предположить. Изучите конкретные различия между двумя вариантами, а затем хорошенько подумайте о последствиях. Обычно вы найдете удивительно проницательное и умное решение неясной проблемы, которое разработчик языка вставил в него специально для того, чтобы облегчить вам жизнь. Будьте соответственно благодарны и воспользуйтесь этим.

person Yrth    schedule 31.07.2020
comment
@jwdonahue: Когда меня пригласили присоединиться к команде разработчиков функций C #, я почти десять лет был профессиональным разработчиком компиляторов и языковым дизайнером и был безусловно самым молодым человеком в этой комнате. Команда разработчиков C # наверняка воспользуется прекрасными идеями, исходящими от стажеров; представление о недостатке опыта в проектировании, оценке, определении и реализации языковых функций в группе разработчиков C # не соответствует действительности. - person Eric Lippert; 05.03.2021
comment
Точно так же этот ответ начинается с причудливого и совершенно противоположного факту предположения о том, что авторы руководящих принципов по разработке фреймворков просто составляют список своих предпочтений. Нет ничего более далекого от правды. Мы активно обсуждали эти руководящие принципы в зале, полном экспертов и заинтересованных сторон; они были продуктом тщательного рассмотрения потребностей профессиональных разработчиков. - person Eric Lippert; 05.03.2021
comment
@EricLippert, оглядываясь назад, я не должен был озвучивать эту глупую мысль. Извинения. - person jwdonahue; 06.03.2021
comment
Я думаю, что в остальном это твердый ответ, который уменьшен (и, вероятно, отвергнут из-за) первого и последнего абзацев. Предлагаю просто убрать первый и последний абзацы. - person andrewf; 30.06.2021

Лучше всего, если те по умолчанию, использующие, например, «ссылки», используемые в исходном решении, должны находиться за пределами пространств имен, а те, которые являются «новой добавленной ссылкой» < / strong> - хорошая практика, вы должны поместить его в пространство имен. Это нужно для того, чтобы различать, какие ссылки добавляются.

person Israel Ocbina    schedule 14.10.2014
comment
Нет, вообще-то это плохая идея. Вы не должны основывать расположение между директивами using с локальной и глобальной областью видимости на том факте, что они добавлены недавно или нет. Вместо этого рекомендуется расположить их в алфавитном порядке, за исключением ссылок BCL, которые должны располагаться сверху. - person Abel; 03.11.2014