Модификатор static в C
В C# есть классы, которые не предназначены для того, чтобы создавать экземпляры. Например, это классы Console, Environment, Math и ThreadPool. Они имеют модификатор static и именуются статическими. Обращаться к методу такого класса можно напрямую, с помощью оператора точка, минуя создание объекта.
В языке появляются новые возможности с каждой новой версией. Использование статики не стоит на месте.
Начиная с версии C#8.0 появилась возможность добавить статику в локальную функцию. А начиная с девятой версии есть возможность добавлять модификатор для лямбда-выражений.
Зачем нужны
Существование таких классов обусловлено тем, что нужно группировать логически связанные сущности. Например, в классе math есть множество методов, которые совершают математические операторы. Для таких классов и существует слово static. Это слово не применяется к структурам, а на статический класс распространяются ограничения.
Пример использования метода класса Math:
int result;
int div = Math.DivRem(19, 7, out result); //переменная div принимает //значение, возвращаемое методом DivRem — остаток от деления нацело
//result = 5
// div = 2
При этом произошло обращение к методу напрямую, без создания нового объекта. Если класс объявлен как статичный, в нём могут быть только статичные методы и переменные. Класс нельзя использовать для создания объектов. В эти классы чаще всего объединяют вспомогательные методы или переменные, которые должны быть доступны для всего приложения.
Когда языки были процедурными, а не объектно-ориентированными, можно было создавать переменные или методы, не принадлежащие объединенному классу, они назывались глобальными. Но теперь это понятие устарело, обращаются к статичному члену класса через имя класса, а нестатичные данные относятся к объекту.
Для нестатичных сущностей нужна инициализация объекта из класса. Иными словами, статичные методы, классы и подобные члены в определенных случаях экономят время программиста и сокращают длину кода. Инициализируются статические переменные в конструкторе.
Пример класса со статикой:
static class Class1
{
public static void DoIt() { /*…*/ }
public static void DoItElse() { /*…*/ }
}
Ограничения
Статическими можно объявлять свойства, а также поля и методы. события, конструкторы, операторы. Но если класс объявлен статическим, все его поля и методы также будут статическими. У статического класса немало ограничений:
- У такого класса не должно быть никаких интерфейсов, поскольку интерфейсы вызываются через экземпляры, а экземпляров нет.
- Данный класс должен быть потомком System.Object.
- В классе есть только статические члены, другие определить нельзя, иначе будет ошибка компиляции. Класс невозможно использовать как поле параметр метода или что-либо еще.
- Сам модификатор static применяется для того, чтобы объявить статический член. Этот модификатор может использоваться чтобы объявить класс static. В классах можно добавить static полям, методам и свойствам.
- На член static нельзя ссылаться через экземпляр, только через имя типа. Слово this нельзя использовать для того, чтобы ссылаться на методы static.
Статические методы
Статические методы класса, исходя из этимологии слова «статика» — это что-то не изменяющиеся. Поля и методы с модификатором static относятся ко всему классу. Если рассматривать память, которая выделяется для статических полей и методов, под этот метод создается отдельный участок, который будет общим для всех объектов.
public static class TemperatureConverter
{
public static double CelsToFahrenheit(string temperatureCelsius)
{
// Конверсия аргумента
double cels = Double.Parse(temperatureCels);
// Конверсия из Цельсия в Фаренггейты
double fahrenheit = (cels * 9 / 5) + 32;
return fahrenheit;
} public static double FahrenheitToCels(string temperatureFahrenheit)
{ // Конверсия аргумента
double fahrenheit = Double.Parse(temperatureFahrenheit);
// Конверсия из Фаренгейта в Цельсий
double cels = (fahrenheit — 32) * 5 / 9;
return cels;
}
}
Конструкторы с модификатором static
Такой конструктор применяется для того, чтобы инициализировать сущности, относящиеся не к какому-то объекту класса, а ко всему классу. Инициализация с помощью статичного конструктора происходит до того, как появятся объекты класса.
Пример:
class Class2
{
public static int m;
public int n;// конструктор статический
static Class2()
{
m = 11;
}// конструктор обычный
public Class2()
{
n = 13;
}
}class Program
{
static void Main(string[] args)
{
Console.WriteLine(«Доступ к экземпляру класса m: » + Class2.m);Class2 obj = new Class2();
Console.WriteLine(«Доступ к экземпляру класса n: » + obj.n);Console.ReadLine();
}
}
Переменные и статика
Логично было бы поинтересоваться, можно ли объявить статическую переменную в статическом методе. Например, написав такой код:
public static void MyMethod3()
{
static int y = 0;
y++;
}
Такие конструкции не поддерживаются в стандарте языка, об этом можно прочитать на MSDN. Но можно использовать статическое поле:
public class Class3
{
private static int Variable3 = 10;public static void Method3()
{
Variable3++;
}
}
Какой класс лучше создать
Удобнее всего статичные сущности применять для того, чтобы создать методы, обеспечивающие шаблоны обработки, вычисления, формат вывода строк и прочее. Если рассмотреть класс System.IO.File, то он статичный, имеет метод Exists(). Для вызова не требуется создание объекта File. А вызывается он подобно вызову любых таких методов:
System.IO.File.Exists(filePath)
Если же нужно создать несколько объектов, то рационально применить динамические классы, например:
public class Produce
{
public string ProduceName { get; private set; }
public int ProduceID { get; private set; }{
this.ProduceName = produceName;
this.ProduceID = produceID;}
}
Заключение
Можно рассмотреть статичность с точки зрения рациональности. Вполне обоснованно задаться вопросом, зачем вообще нужен этот механизм и почему нельзя добиться того же другими средствами. Как правило, если нужен доступ к методу какого-то класса, создается объект класса и потом уже обращение к экземпляру. Но к статичному методу можно обращаться без создания объекта.
Нечто подобное происходит, когда включается метод Main в программу. При запуске происходит вызов этого метода. Но происходит это не только благодаря особому имени — main, а потому, что присутствует ключевое слово static, и не нужно создание экземпляров класса. Таким образом, точка входа в программу обусловлена механизмом статичности.
Статичный метод может использовать только переменные, которые объявлены внутри этого метода. Можно использовать и внешние по отношению к методу, но они должны быть статичными. Так как методы и переменные статичного типа система создаёт автоматически и прикрепляет их к классу, а не объекту, инициализация нового объекта не происходит. Выделение памяти под статичные переменные, сколько бы объектов не было создано, всегда будет в единственном числе, причем значение переменных будет как бы в равной степени им принадлежать.
Это интересное свойство статических форм. Классический пример — это число объектов, созданных из одного класса. В отличие от статичных, нестатичные переменные у каждого объекта свои. Если меняется не статичное поле, в этом случае значение переменной сбрасывается при создании любого экземпляра. Для подсчета новых объектов нужно использовать статический конструктор. Тогда счётчики не будут сбрасываться, конструктор будет одноименным с классом.