Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
namespace Example
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("before static ctor");
C c = new C();
Console.WriteLine("after static ctor");
}
}
class C
{
static C()
{
Console.WriteLine("from static ctor");
}
public C()
{
}
}
}Кроме того, CLR ведет себя довольно свободно, принимая решение о вызове кон-
структора типа. CLR вызывает конструктор типа в одном из следующих случаев.
• Прямо перед созданием первого экземпляра типа или перед первым обраще-
нием к полю или члену класса, не унаследованному от предка. Это называется
точной семантикой, поскольку CLR вызывает конструктор типа именно в тот
момент, когда он необходим.
• В любое время перед первым обращением к статическому полю, не унаследо-
ванному от предка. Это семантика с заблаговременной инициализацией поля,
так как CLR гарантирует лишь то, что статический конструктор будет испол-
нен до обращения к статическому полю, возможно, задолго до него.
По умолчанию компиляторы сами выбирают семантику, наиболее подходящую
для вашего типа, и информируют CLR о выборе, устанавливая в метаданных флаг
b e f o r e f i e l d i n i t .
The laziness of type initializers is only guaranteed by .NET when the type isn't marked with a special flag called beforefieldinit. Unfortunately, the C# compiler (as provided in the .NET 1.1 runtime, at least) marks all types which don't have a static constructor (i.e. a block which looks like a constructor but is marked static) as beforefieldinit
If not marked BeforeFieldInit then that type's initializer method is executed at (i.e., is triggered by):
*first access to any static or instance field of that type, or
*first invocation of any static, instance or virtual method of that type
namespace Etude_7
{
public class Program
{
static Program()
{
Console.WriteLine("Before static .ctor");
C c = new C();
Console.WriteLine("After static .ctor");
}
public static void Main()
{
Console.ReadLine();
}
}
public class C
{
private static Program _program = new Program();
static C()
{
Console.WriteLine("from static .ctor");
}
}
}
class C
{
private static Action s_orderedCtor = null;
private static bool s_allowCtor = false;
private static object s_sync = new object();
public static void AllowCtor()
{
lock (s_sync)
{
if (s_allowCtor)
return;
if (s_orderedCtor != null)
s_orderedCtor();
s_allowCtor = true;
}
}
static C()
{
lock (s_sync)
{
Action ctor = delegate()
{
Console.WriteLine("from static ctor");
};
if (s_allowCtor)
ctor();
else
s_orderedCtor = ctor;
}
}
public C()
{
AllowCtor();
Console.WriteLine("from non-static ctor");
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("before static ctor");
C.AllowCtor();
Console.WriteLine("after static ctor");
C c = new C();
c = new C();
Console.ReadKey();
}
}
Console.WriteLine("before static ctor");
Action action = () => new C();
action(); //call of static ctor
Console.WriteLine("after static ctor");internal class Program {
private static void Main(string[] args) {
Console.WriteLine("before static ctor");
var c2 = Factory.Instance;
Console.WriteLine("after static ctor");
Console.ReadLine();
}
}
public static class Factory {
private static AppDomain domain;
private static readonly object syncRoot = new object();
public static object Instance {
get {
lock (syncRoot) {
if (domain != null)
AppDomain.Unload(domain);
domain = AppDomain.CreateDomain(Guid.NewGuid().ToString());
}
return domain.CreateInstanceAndUnwrap(
"ConsoleApplication1",
"ConsoleApplication1.Factory+C");
}
}
private class C : MarshalByRefObject {
static C() { Console.WriteLine("from static ctor"); }
}
}
C#: Этюды, часть 7