Сегодня у меня возникла ошибка при попытке отформатировать существующий код. Первоначально в коде директивы using были объявлены вне пространства имен:
using System.Collections.Generic;
namespace MyNamespace
{
using IntPair = KeyValuePair<int, int>;
}
Когда я попытался вставить директиву using внутрь оператора (чтобы соответствовать правилам StyleCop), я получил ошибку в директиве псевдонима, и мне пришлось ее полностью квалифицировать:
namespace MyNamespace
{
using System.Collections.Generic;
//using IntPair = KeyValuePair<int, int>; // Error!
using IntPair = System.Collections.Generic.KeyValuePair<int, int>; // works
}
Интересно, какая разница между этими двумя случаями? Имеет ли значение расположение директивы using (в стиле импорта)?





Раньше я думал, что это не имеет значения, но я всегда хорошо разбираюсь в командах.
Обновлено: проверил Спецификация C#, в разделе 9.4 говорится, что:
The scope of a using-directive specifically does not include its peer using-directives. Thus, peer using-directives do not affect each other, and the order in which they are written is insignificant.
Поэтому, если System.Collections.Generic и KeyValuePair рассматриваются как одноранговые узлы, KeyValuePair игнорирует System.Collections.Generic.
Да, в некоторой степени. Существует крайний случай, связанный с областью / локальными именами, см. Блог Эрика Липперта.
Для конкретного примера (специфичного для использования псевдонима):
using System;
using Foo = Bar;
public static class Bar {
public static void Test() { Console.WriteLine("outer"); }
}
namespace MyNamespace {
//using Foo = Bar;
public static class Bar {
public static void Test() { Console.WriteLine("inner"); }
}
static class Program {
static void Main() {
Foo.Test();
}
}
}
Да, у меня есть рабочий пример для аналогичного вопрос (коллизии пространств имен).
По сути, правила поиска имени различаются, если директива using является глобальной (вне пространства имен) или внутри пространства имен, когда она имеет более высокий приоритет.
Это чисто информационный характер, поскольку в одном из ответов утверждается, что это влияет на время загрузки сборки; но на самом деле сборки загружаются в первый раз, когда метод / тип, использующий их, JITted (или доступен через отражение и т. д.).
Вот пример, показывающий, что это не имеет значения; если using находится в любом месте, результат будет одинаковым: System.Core загружается, когда Bar получает JITted:
pre-Bar
System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
pre-Max
Max: 5
post-Max
post-Bar
пример (запускать из командной строки, а не в отладчике; в идеале в конфигурации выпуска):
using System;
//using System.Linq;
namespace Foo {
using System.Linq;
class Program {
static Program() {
AppDomain.CurrentDomain.AssemblyLoad += (s, a) => {
Console.WriteLine(a.LoadedAssembly.FullName);
};
}
static void Main() {
Console.WriteLine("pre-Bar");
Bar();
Console.WriteLine("post-Bar");
Console.ReadLine();
}
static void Bar() {
Console.WriteLine("pre-Max");
int[] data = { 1, 2, 3, 4, 5 };
Console.WriteLine("Max: " + Enumerable.Max(data));
Console.WriteLine("post-Max");
}
}
}