День двести тридцать пятый. #ЗаметкиНаПолях

Использование using static

Директива using static служит для упрощённого импорта следующих членов классов:

1. Статические поля, свойства и методы. Канонический пример – использование класса Math:

using static System.Math;



// перевод градусов в радианы, используя Math.PI

double radians = degrees * PI / 180;

// площадь треугольника через Math.Sin

double area = 1/2 * sideA * sideB * Sin(angle);

2. Значения перечислений. Это полезно, если в коде много раз используются значения перечисления. В примере ниже перебираются значения перечисления HttpStatusCode. Добавив using static, в операторе switch можно опускать имя перечисления:

using static System.Net.HttpStatusCode;

...

switch (response.StatusCode)

{

case OK: …

case TemporaryRedirect: …

case Redirect: …

case RedirectMethod: …

case NotFound: …

default: …

}

3. Вложенные типы.

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



Методы расширения и using static

Два важных момента взаимодействия методов расширения и директивы using static:

1. Методы расширения из одного типа могут быть импортированы с использованием директивы using static с этим типом без импорта каких-либо методов расширения из остальной части данного пространства имен. Например, класс System.Linq.Queryable содержит методы расширения для деревьев выражений IQueryable<T>, а класс System.Linq.Enumerable содержит методы расширения для делегатов, принимающих IEnumerable<T>. Поскольку IQueryable<T> наследуется от IEnumerable<T>, используя обычную директиву using для System.Linq, вы можете использовать методы расширения, принимающие делегаты в IQueryable<T>, хотя обычно этого не требуется. Далее показано, как использование статической директивы только для System.Linq.Queryable приводит к тому, что методы расширения из System.Linq.Enumerable не подключаются:

using System.Linq.Expressions;

using static System.Linq.Queryable;

...

var query = new[] { "a", "bc", "d" }.AsQueryable();

Expression<Func<string, bool>> expr = x => x.Length > 1;

Func<string, bool> del = x => x.Length > 1;

var valid = query.Where(expr);

var invalid = query.Where(del);

Последняя строка приводит к ошибке компиляции, поскольку методу Where передаётся делегат, а не дерево выражений. Таким образом, если у вас в проекте есть файл с методами расширения для различных типов проекта, можно разделить методы расширения, относящиеся к разным типам, на разные классы расширений и импортировать каждый класс по отдельности с помощью using static.

2. Методы расширения, импортированные из типа, нельзя вызывать, как статический методы (как выше вызывался метод Sin класса Math). Вместо этого вы должны вызывать их, как если бы они были экземплярами методов расширяемого типа. Например, метод расширения Enumerable.Count:

using System.Collections.Generic;

using static System.Linq.Enumerable;



IEnumerable<string> strings = new[] { "a", "b", "c" };

int valid = strings.Count();

int invalid = Count(strings);

Последняя строка приведёт к ошибке компиляции.



Источник: Jon Skeet “C# In Depth”. 4th ed – Manning Publications Co, 2019. Глава 10.