Pull to refresh

Статика в C#

Reading time4 min
Views176K
Волею судьбы в последние годы у меня появилось ещё одно очень увлекательное хобби – учить. Я занимаюсь обучением людей, которые хотят стать программистами C#. Люди приходят разные: технари, гуманитарии, кто-то по своей воле, кого-то направляют от организаций. Не смотря на различные уровни, мне нужно их обучать. Поэтому я стараюсь постоянно обновлять и улучшать свои обучающие материалы. В связи с чем, пришёл к выводу: «А не плохо было бы оформить материалы в текстовом виде, чтобы ими было удобно пользоваться». Под катом я выложил как пример одну из недавно оформленных лекций.


Общая концепция

Перво на перво, следует разобраться что же такое статика. В C# есть ключевое слово static, которое можно применять к:
  • полям
  • свойствам
  • методам
  • операторам
  • событиям
  • конструктору
  • классам


static class OneHuman
{
    public static string Name { get; set; }
    public static int Age { get; set; }

    public static string GetInformation()
    {
            return string.Format("{0} is {1} years old", Name, Age);
    }
}


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

class Program
{
    static void Main(string[] args)
    {
            OneHuman.Name = "Onizuka";
            OneHuman.Age = 22;

            Console.WriteLine(OneHuman.GetInformation());
    }
}


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

class Box
{
    public static string DefaultContext { get; set; }

    public string Context { get; set; }
}


Если весь класс является статическим:
  • Нельзя создавать экземпляр класса, используя ключевое слово new.
  • Не разрешается использовать не статические члены этого же класса.
  • Он не поддерживает наследование.
  • Невозможно перегрузить методы.


Если класс не является статическим, но содержит статические методы, то на эти методы распространяются следующие ограничения:
  • Не разрешается использовать не статические члены этого же класса из статических. Конечно же, вам никто не мешает создать экземпляр класса в статическом методе.
  • Наследование и полиморфизм для статических членов не поддерживаются.


Больше деталей

Выше мы не рассматривали такую конструкцию, как статический конструктор. Один из достаточно интересных вопросов, на мой взгляд, когда происходит вызов статического конструктор у классов?

class Box
{
    static Box()
    {
            Console.WriteLine("static ctor was called");
    }

    public Box()
    {
            Console.WriteLine("default ctor was calleds");
    }

    public static string Data { get { return "You are trying to get data"; } }

    public const int Foo = 7;
}


Я думаю вы уже обратили внимание, что для статического конструктора не используется спецификатор доступа. Всё очень очевидно, создание статики вы не контролируете. Если попробовать выполнить приведённый ниже код, то можно убедиться в верности следующего утверждения: статический конструктор вызывается перед доступом к любому члену класса.

class Program
{
    static void Main(string[] args)
    {
        var data = Box.Data;
        var box = new Box();
    }
}

Можно поиграться, закомментировав любую из строк в которых происходит обращение к классу Box. Теперь немного изменим код, и подправим наше утверждение

class Program
{
    static void Main(string[] args)
    {
            var data = Box.Foo;
    }
}


В данном случае вызов статического конструктора не происходит. Итак: статический конструктор вызывается перед доступом к любому члену класса, за исключением констант. Я не зря использовал слово класс в данном определении. Со структурами очень много “приколов”. Вы должно быть знаете, что в C# нельзя переопределить конструктор по-умолчанию, но можно определить статический конструктор без параметров. Однако он будет вызываться не всегда, так например не произойдёт его вызов, если вы, например, попытаетесь создать массив структур.

Общие рассуждения об использовании статики

Существует относительно много мнений, когда использовать статические классы и когда не стоит так поступать. Исходя из своего опыта, отмечу, статические классы — любимое оружие начинающих разработчиков. Попользовал и забыл — хорошая концепция.
Чтобы разобраться в хитросплетениях о применяемости статики, следует вернуться к понятиям ООП. Представьте что у вас есть велосипед, но велосипед есть так же и у вашего соседа, и у соседа соседа, и т.д. В данном случае статика неприемлема. Т.к. велосипеды могут быть разного цвета, веса, обладать разным количеством колёс. То-бишь различные экземпляры одного и того же вида. Статика же применима для каких-то глобальных объектов\действий, когда не подразумевается создание экземпляров класса(часто для каких-то служебных методов: вывод на консоль — Console.WriteLine(), сортировка массива Array.Sort). Зачастую классы могут предоставлять как статическую, так и не статическую функциональность. Когда же у вас возникают сомнения, остановитесь и подумайте, понадобится ли вам экземпляр “этого”. Если же вы так хотите контролировать создание экземпляров класса или же вообще иметь только один, то для этих целей замечательно пригодится паттерн Singleton. В рамках ООП статика обладает рядом недостатков. Чем же она так плоха?

Полиморфизм

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

Тестирование

При использование статики тестирование достаточно затруднено. Нельзя оперативно подменять код, основываясь на интерфейсах. Если нужно менять, то серьёзно, переписывая значительные куски кода.

Единственная ответственность

Статические методы, зачастую, применяются для служебных целей, будь-то вывод в лог ошибок или сортировка массива. Поэтому иногда возникает желание запихнуть всю статическую функциональность в один класс, обозвав его MegaUtils. Так поступать не стоит, лучше создать целую кучу маленьких классов, отвечающих каждый за свою область деятельности.
Tags:
Hubs:
Total votes 34: ↑23 and ↓11+12
Comments16

Articles