Что такое использование статических конструкторов?


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

9 243

9 ответов:

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

Он запускается автоматически во время выполнения при первой необходимости (точные правила там сложны (см. "beforefieldinit") и тонко изменяются между CLR2 и CLR4). Если вы не злоупотребляете отражением, он гарантированно работает максимум один раз (даже если два потока поступают одновременно).

С Статические Конструкторы (Руководство По Программированию На C#):

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

статические конструкторы имеют следующие свойства:

  • статический конструктор не принимает доступ модификаторы или параметры.

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

  • статический конструктор не может быть вызван напрямую.

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

  • типичное использование статических конструкторов, когда класс использует файл журнала и конструктор используется для записи в этот файл.

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

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

Пример: Предположим, что у нас был этот класс:

class ScopeMonitor
{
    static string urlFragment = "foo/bar";
    static string firstPart= "http://www.example.com/";
    static string fullUrl= firstPart + urlFragment;
}

когда вы получаете доступ fullUr будет "http://www.example.com/foo/bar".

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

class ScopeMonitor
{
    static string firstPart= "http://www.example.com/";
    static string fullUrl= firstPart + urlFragment;
    static string urlFragment = "foo/bar";
}

код fullUrl значение теперь просто "http://www.example.com/ " С тех пор urlFragment не был инициализирован в то время fullUrl не имеет. Не хороший. Итак, вы добавляете статический конструктор, чтобы позаботиться о инициализация:

class ScopeMonitor
{
    static string firstPart= "http://www.example.com/";
    static string fullUrl;
    static string urlFragment = "foo/bar";

    static ScopeMonitor()
    {
        fullUrl= firstPart + urlFragment;

    }
}

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

1.It может получить доступ только к статическим членам класса.

причина: нестатический элемент является специфичным для экземпляра объекта. Если статическому конструктору разрешено работать с нестатическими членами, он будет отражать изменения во всех экземплярах объекта, что нецелесообразно.

2.В статическом конструкторе не должно быть параметров.

причина: поскольку он будет вызван CLR, никто не может передать ему параметр. 3.Только один статический конструктор допустимый.

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

4.Там не должно быть модификатора доступа к нему.

причина: опять же причина в том, что тот же вызов статического конструктора выполняется CLR, а не объектом, не нужно иметь модификатор доступа к нему

вы можете использовать статический конструктор для инициализации статических полей. Он выполняется в неопределенное время до использования этих полей. Документация Microsoft и многие разработчики предупреждают, что статические конструкторы для типа накладывают значительные накладные расходы.
лучше избегать статических конструкторов для максимальной производительности.
обновление: вы не можете использовать более одного статического конструктора в одном классе, однако вы можете использовать другие конструкторы экземпляров с (максимум) одним статическим конструктор.

почему и когда мы создадим статический конструктор ...?

один конкретные причина использования статического конструктора заключается в создании класса "super enum". Вот (простой, надуманный) пример:

public class Animals
{
    private readonly string _description;
    private readonly string _speciesBinomialName;

    public string Description { get { return _description; } }
    public string SpeciesBinomialName { get { return _speciesBinomialName; } }

    private Animals(string description, string speciesBinomialName)
    {
        _description = description;
        _speciesBinomialName = speciesBinomialName;
    }

    private static readonly Animals _dog;
    private static readonly Animals _cat;
    private static readonly Animals _boaConstrictor;

    public static Animals Dog { get { return _dog; } }
    public static Animals Cat { get { return _cat; } }
    public static Animals BoaConstrictor { get { return _boaConstrictor; } }

    static Animals()
    {
        _dog = new Animals("Man's best friend", "Canis familiaris");
        _cat = new Animals("Small, typically furry, killer", "Felis catus");
        _boaConstrictor = new Animals("Large, heavy-bodied snake", "Boa constrictor");
    }
}

вы бы использовали его очень похожим (в синтаксическом виде) на любое другое перечисление:

Animals.Dog

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

Статический Конструктор

конструктор, объявленный с использованием модификатора static статический конструктор. Статический конструктор используется для инициализации статических данных или для выполнения определенного действия, которое необходимо выполнить только один раз в жизненном цикле класса. Статический конструктор-это первый блок кода для выполнения в классе. Статический конструктор выполняется только один раз в жизненном цикле классе. Он вызывается автоматически. Статический конструктор не принимает никаких параметров. Оно не имеет спецификаторов доступа. Это не называется напрямую.

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

Источник: http://www.c-sharpcorner.com/article/static-constructor-in-C-Sharp-and-their-usages/

using System;
namespace Constructor
{
class Test
{
//Declaration and initialization of static data member 
private static int id = 5;
public static int Id
{
get
{
return id;
}
}
public static void print()
{
Console.WriteLine("Test.id = " + id);
}
static void Main(string[] args)
{
//Print the value of id 
Test.print();
}
}
}

In the above example, static data member <id> is declared and initialized in same line. So if you compile and run this program your output would look similar to this :

Test.id = 5

Lets create one more class similar to class Test but this time the value of its static data member would depend on the value of static data member <id> of class Test.id.

//File Name : Test1.cs
using System;
namespace Constructor
{
class Test1
{
private static int id ;
//Static constructor, value of data member id is set conditionally here. 
//This type of initialization is not possible at the time of declaration.
static Test1()
{
if( Test.Id < 10 )
{
id = 20;
}
else
{
id = 100; 
}
Console.WriteLine("Static<Class> Constructor for Class Test1 Called..");
}
public static void print()
{
Console.WriteLine("Test1.id = " + id);
}
static void Main(string[] args)
{
//Print the value of id 
Test1.print();
}
}
}

As you can see in the above static constructor, static data member <id> is initialized conditionally. This type of initialization is not possible at the time of declaration. This is where static constructor comes in picture