powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Порядок инициализации конструкторов в c#
25 сообщений из 39, страница 1 из 2
Порядок инициализации конструкторов в c#
    #39508405
stut
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Интересует почему статические конструкторы применяются в обратном порядке, а обычные в прямом порядке - от базового к производному (как в джаве, но вроде бы тоже должны быть в обратном порядке). Например, class A { static A { ... "staticA"...} public A { ..."instanceA"...} } ... class B:A { static B { ... "staticB"...} public B { ..."instanceB"...} }
...
Рейтинг: 0 / 0
Порядок инициализации конструкторов в c#
    #39508419
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
stutа обычные в прямом порядке - от базового к производному
С чего бы это вдруг?
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
class Program
{
  static void Main()
  {
    var c = new C();
    Console.WriteLine(c);
    Console.WriteLine("done");
    Console.ReadKey(true);
  }

  class A
  {
  }

  class B : A
  {
  }

  class C : B
  {
  }
}


Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
.method private hidebysig static void  Main() cil managed
{
  .entrypoint
  // Code size       33 (0x21)
  .maxstack  1
  .locals init ([0] class test17.Program/C c)
  IL_0000:  nop
  IL_0001:  newobj     instance void test17.Program/C::.ctor()
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  call       void [mscorlib]System.Console::WriteLine(object)
  IL_000d:  nop
  IL_000e:  ldstr      "done"
  IL_0013:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_0018:  nop
  IL_0019:  ldc.i4.1
  IL_001a:  call       valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey(bool)
  IL_001f:  pop
  IL_0020:  ret
} // end of method Program::Main

.method public hidebysig specialname rtspecialname 
        instance void  .ctor() cil managed
{
  // Code size       8 (0x8)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  call       instance void test17.Program/B::.ctor()
  IL_0006:  nop
  IL_0007:  ret
} // end of method C::.ctor

.method public hidebysig specialname rtspecialname 
        instance void  .ctor() cil managed
{
  // Code size       8 (0x8)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  call       instance void test17.Program/A::.ctor()
  IL_0006:  nop
  IL_0007:  ret
} // end of method B::.ctor

.method public hidebysig specialname rtspecialname 
        instance void  .ctor() cil managed
{
  // Code size       8 (0x8)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
  IL_0006:  nop
  IL_0007:  ret
} // end of method A::.ctor


- все тот же вызов от производного к базовому. Просто вызов непараметриризованного конструктора базового класса неявно вставляется в конструктор производного класса первым (а в случае отсутствия такового пришлось бы руками писать base(arglist), и этой путаницы бы не было), поэтому и кажется, что он вызывается раньше.
...
Рейтинг: 0 / 0
Порядок инициализации конструкторов в c#
    #39508432
stut
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я сейчас проверить не могу - но все-таки выходит так что сперва вызывается конструктор производного класа, а потом базового (не так как в джаве, по вашему)? В общем случае? Но у меня пример когда есть именно конструктор А и В без параметров, которые лиш как маркеры для проверки выводят некую строку. Проверял, работают от сверху вниз, а статические наоборот. И почему кажется что раньше: B b=new B(); выводит -> staticB->staticA->instanceA->instanceB -- если это исключение для чего то разворачивать порядок. А если будут использоватся лиш дефолтные конструкторы то порядок будет обратный? Но проверить не будет возможно, хотя бы так наочно как здесь.
...
Рейтинг: 0 / 0
Порядок инициализации конструкторов в c#
    #39508451
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/classes-and-structs/static-constructors Статический конструктор используется для инициализации любых статических данных или для выполнения определенного действия, которое требуется выполнить только один раз. Он вызывается автоматически перед созданием первого экземпляра или ссылкой на какие-либо статические члены.
Если из статического конструктора B() ты не обращаешься к классу A, то при
Код: c#
1.
B b = new B();


сначала вызовется static B(), затем A(), в начале которого вызовется static A()

Ключевое тут: не обращаешься к классу A, поэтому без разницы в каком порядке статические конструкторы отработают.
Добавь в static B() обращение к чему-нибудь static из A() и static A() отработает раньше.
...
Рейтинг: 0 / 0
Порядок инициализации конструкторов в c#
    #39508454
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
stutB b=new B(); выводит -> staticB->staticA->instanceA->instanceB
Порядок вызовов на самом деле такой: staticB->staticA и instanceB->instanceA, но вызов instancA - первый в теле instanceB. А со статиками и так всё понятно: кто первый используется, того статический конструктор первым и вызывается. Если первый используется B , то первым вызывается его статический конструктор, а поскольку B ссылается на А, то вторым вызывается стат. конструктор А. А поскольку стат. мемберы не наследуются, то и вызова стат. конструкторов по иерархии наследования нет.
...
Рейтинг: 0 / 0
Порядок инициализации конструкторов в c#
    #39508550
stut
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вы привели ссылку на статические конструкторы - лутче б привели ссылку на стандартные конструкторы - не знал донедавна что они настолько отличаются от явы. Хотя перед этим где то было подчеркнуто, что при явном вызове базового конструктора он в шарпе находится в не тела конкретного конструктора. А что случается при неявном вызове непонятно, как в моем примере. Но здесь важен результат. В моем примере сперва появляется InstanceA, а потом InstanceB. Касательно утверждение что среди статических конструкторов сперва вызывается тот кто первым используется - то в моем примере нету статических полей потому здесь применяется какое то дефолтное правило. Вот никогда не обращал внимание что статические переменные не наследуются - но в примере обьекта производного класа В -- появляются строки которые пишет сперва стат. констр. класа В, а потом А.
...
Рейтинг: 0 / 0
Порядок инициализации конструкторов в c#
    #39508575
Фотография LR
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
stutА что случается при неявном вызове непонятно, как в моем примере. Но здесь важен результат. В моем примере сперва появляется InstanceA, а потом InstanceB.
Выше уже писали
...
Рейтинг: 0 / 0
Порядок инициализации конструкторов в c#
    #39508578
Фотография LR
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LRstutА что случается при неявном вызове непонятно, как в моем примере. Но здесь важен результат. В моем примере сперва появляется InstanceA, а потом InstanceB.
Выше уже писали
Выше уже писали
Сон Веры ПавловныПорядок вызовов на самом деле такой: staticB->staticA и instanceB->instanceA, но вызов instancA - первый в теле instanceB.
А чтобы убедиться воочию, можно использовать инициализацию полей, вот здесь во втором ответе хороший пример
https://social.msdn.microsoft.com/Forums/vstudio/en-US/38a49e82-7404-4222-8a67-88ee3973e475/order-of-execution-of-static-constructor-in-case-of-inheritance-in-c?forum=csharpgeneral Before executing its code, instance constructor of B makes a call to the base constructor:
- Static constructor of A is called
- Instance constructor of A is called
To check exactly what the order is, you need to have code executed just before the base constructor is called, i.e. during fields initialization
...
Рейтинг: 0 / 0
Порядок инициализации конструкторов в c#
    #39508593
stut
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Собственно порядок вызовов мне не важен - хотя теперь интересно а какой он в jаvа - важен кто придет первый к финишу. И кажется в джаве конструктор вызывается в теле конструктора базового класа - а в шарпе - class B:A { public B:base () {...}. Хотя это явный вариант - может в неявном варианте конструктор базового класа получается и в теле производного конструктора. Вообще хотелось бы получить ссылку на официальную документацию о порядке инициализации нестатических контструкторов при наследовании в шарпе.
...
Рейтинг: 0 / 0
Порядок инициализации конструкторов в c#
    #39508612
Фотография LR
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
stutВообще хотелось бы получить ссылку на официальную документацию о порядке инициализации нестатических контструкторов при наследовании в шарпе.
C# Language Specification \ Classes \ Instance constructors \ Constructor execution - оно?
...
Рейтинг: 0 / 0
Порядок инициализации конструкторов в c#
    #39510898
stut
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LR, ссылка или ресурс несколько сумбурный. Надо чтобы как в джаве было написано - вот сперва конструктор базового класа, а потом класов наследников. Если вы пишите что конструктор вызывается в теле то я так понимаю что в вышеприденом непараметризированом и недефолтном конструкторе производится имплиситное преобразование public В() { Console.Write(); } => public B() { /* base() */ A(); Console.Write();} Ибо в шарпе при прямом вызове конструктора обычно пишут public B: base() // A() {Console.Write ();} В этом случае конструктор получается в не тела, и вызов идет в обратном порядке? Но где прямо об этих двух случаях написано официально.
...
Рейтинг: 0 / 0
Порядок инициализации конструкторов в c#
    #39510966
refreg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LR C# Language Specification \ Classes \ Instance constructors \ Constructor execution - оно?stutLR, ссылка или ресурс несколько сумбурный. Надо чтобы как в джаве было написано - вот сперва конструктор базового класа, а потом класов наследников. Если вы пишите что конструктор вызывается в теле то я так понимаю что в вышеприденом непараметризированом и недефолтном конструкторе производится имплиситное преобразование public В() { Console.Write(); } => public B() { /* base() */ A(); Console.Write();} Ибо в шарпе при прямом вызове конструктора обычно пишут public B: base() // A() {Console.Write ();} В этом случае конструктор получается в не тела, и вызов идет в обратном порядке? Но где прямо об этих двух случаях написано официально.
По той же ссылке:
10.10.1 Constructor initializers
Visual Studio .NET 2003

All instance constructors (except those for class object) implicitly include an invocation of another instance constructor immediately before the constructor-body. The constructor to implicitly invoke is determined by the constructor-initializer.

про статические в 10.11

Те это для суда надо?
...
Рейтинг: 0 / 0
Порядок инициализации конструкторов в c#
    #39510975
stut
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
refreg, all other constructors - но не сказано что они есть в иерархии наследования. И вы же сами привели цыцату, что перед телом конструктора, а не в теле. И что значит before body - что логически сперва исполняется код перед телом, а потом собственно сам блок кода конструктора? В яве как раз все в теле конструктора и сперва инициализация старших конструкоров, хотя наверное если вписать super() в конец то будет наоборот.
...
Рейтинг: 0 / 0
Порядок инициализации конструкторов в c#
    #39510992
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
stutrefreg, all other constructors - но не сказано что они есть в иерархии наследования. И вы же сами привели цыцату, что перед телом конструктора, а не в теле. И что значит before body - что логически сперва исполняется код перед телом, а потом собственно сам блок кода конструктора? В яве как раз все в теле конструктора и сперва инициализация старших конструкоров, хотя наверное если вписать super() в конец то будет наоборот.
Я ссылку выше дал 20739051 русским по белому расписано как работает.
...
Рейтинг: 0 / 0
Порядок инициализации конструкторов в c#
    #39510996
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
stutrefreg, all other constructors - но не сказано что они есть в иерархии наследования
Не all others, a all instance constructors. Если конструктора нет в иерархии наследования, то это может означать только одно - явноя инстанциирование экземпляра другого класса в конструкторе, к рассматриваемому вопросу данный случай не относится.
Ну и, наконец, вполне можно убедиться самому. Короткий пример выше я приводил, вот более развернутый. Из IL-кода прекрасно видно, как это происходит (в полном соответствии с документацией, и с тем, что здесь про всё это писали):
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
class Program
{
  static void Main()
  {
    var c = new C();
    Console.WriteLine(c);
  }

  class A
  {
    int _a = 1;
    public A()
    {
      Console.WriteLine("A");
    }
  }

  class B : A
  {
    int _b = 2;
    public B()
    {
      Console.WriteLine("B");
    }
  }

  class C : B
  {
    int _c = 3;
    public C()
    {
      Console.WriteLine("C");
    }
  }
}



Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
.method private hidebysig static void  Main() cil managed
{
  .entrypoint
  .maxstack  8
  IL_0000:  newobj     instance void test.Program/C::.ctor()
  IL_0005:  call       void [mscorlib]System.Console::WriteLine(object)
  IL_000a:  ret
} // end of method Program::Main

.method public hidebysig specialname rtspecialname 
        instance void  .ctor() cil managed
{
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  ldc.i4.1
  IL_0002:  stfld      int32 test.Program/A::_a
  IL_0007:  ldarg.0
  IL_0008:  call       instance void [mscorlib]System.Object::.ctor()
  IL_000d:  ldstr      "A"
  IL_0012:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_0017:  ret
} // end of method A::.ctor

.method public hidebysig specialname rtspecialname 
        instance void  .ctor() cil managed
{
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  ldc.i4.2
  IL_0002:  stfld      int32 test.Program/B::_b
  IL_0007:  ldarg.0
  IL_0008:  call       instance void test.Program/A::.ctor()
  IL_000d:  ldstr      "B"
  IL_0012:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_0017:  ret
} // end of method B::.ctor

.method public hidebysig specialname rtspecialname 
        instance void  .ctor() cil managed
{
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  ldc.i4.3
  IL_0002:  stfld      int32 test.Program/C::_c
  IL_0007:  ldarg.0
  IL_0008:  call       instance void test.Program/B::.ctor()
  IL_000d:  ldstr      "C"
  IL_0012:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_0017:  ret
} // end of method C::.ctor
...
Рейтинг: 0 / 0
Порядок инициализации конструкторов в c#
    #39511000
refreg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
stutrefreg, all other constructors - но не сказано что они есть в иерархии наследования. И вы же сами привели цыцату, что перед телом конструктора, а не в теле. И что значит before body - что логически сперва исполняется код перед телом, а потом собственно сам блок кода конструктора? В яве как раз все в теле конструктора и сперва инициализация старших конструкоров, хотя наверное если вписать super() в конец то будет наоборот.Вот те еще выдержка из того же раздела:
If an instance constructor has no constructor initializer, a constructor initializer of the form base() is implicitly provided. Thus, an instance constructor declaration of the form
C(...) {...}
is exactly equivalent to
C(...): base() {...}

Таким образом вызвается тот конструктор, который вызвается, а он перед "телом", вызывает либо то, что прописано (например, там может быть this - не обязательно base) либо base().

Все предельно ясно и точно, никаких прямых и обратных вызововов (я так и не понимаю почему один порядок для тя прямой другой обратный)
...
Рейтинг: 0 / 0
Порядок инициализации конструкторов в c#
    #39511013
Фотография LR
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
stut,
Наверное путаница возникла из-за того, что понятие "конструктор" можно трактовать двояко - в узком смысле, лишь как код в c#-методе-"конструкторе" и в широком смысле - создание реального объекта, смотрите к примеру IL-код method C::.ctor, приведенный выше Сном Веры Павловны (здесь 1.инициализация полей, 2.вызов "широкого" конструктора базового класса, 3.выполнение кода "узкого" конструктора).
Ну а по той ссылке на спецификацию очень доступно объясняется, в т.ч., почему на 1-м месте инициализация полей.
...
Рейтинг: 0 / 0
Порядок инициализации конструкторов в c#
    #39511038
stut
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LR,
вот именно, я как не очень искушенный в практике програмист, по ходу уже перестал понимать что два контструкторы в класе потомке строять один и тот же обьект класа потомка, а не как бы создают два модуля в одном обьекте. Хорошо что джаве статических конструкторов не встречал, хотя может они и есть. Но снова таки: что значит no constructor initializes (я это понимал как дефолтный конструктор). В моем примере дефолт переопределен - public B() {Console.Write("instanceA");}. Инициализация присутсвует. Снова таки было б четко указано про порядок конструкторов с простыми примерами было бы проще. А то уж то очень закручено, с оставшиемися вопросами. Порядок обратный - как бы специально для статиков, но в инстансах -- они имплиситно вызывают базовый конструктор - так напишите на английском со стороны микрософта, с простым примером.
...
Рейтинг: 0 / 0
Порядок инициализации конструкторов в c#
    #39511046
_nautilus_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
stutтак напишите на английском со стороны микрософта, с простым примером.

Так вроде ж написано. Допустим есть

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
class Item1
{}

class Item2 : Item1
{}

class Item3 : Item2
{}



При создании экземляра Item3 первым отработает конструктор object, потом Item1, потом Item2, потом Item3.
...
Рейтинг: 0 / 0
Порядок инициализации конструкторов в c#
    #39511065
refreg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
stutLR,
вот именно, я как не очень искушенный в практике програмист, по ходу уже перестал понимать что два контструкторы в класе потомке строять один и тот же обьект класа потомка, а не как бы создают два модуля в одном обьекте. Хорошо что джаве статических конструкторов не встречал, хотя может они и есть. Но снова таки: что значит no constructor initializes (я это понимал как дефолтный конструктор). В моем примере дефолт переопределен - public B() {Console.Write("instanceA");}. Инициализация присутсвует. Снова таки было б четко указано про порядок конструкторов с простыми примерами было бы проще. А то уж то очень закручено, с оставшиемися вопросами. Порядок обратный - как бы специально для статиков, но в инстансах -- они имплиситно вызывают базовый конструктор - так напишите на английском со стороны микрософта, с простым примером.Какой бардак...
...
Рейтинг: 0 / 0
Порядок инициализации конструкторов в c#
    #39511072
Фотография LR
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
stutНо снова таки: что значит no constructor initializes (я это понимал как дефолтный конструктор). В моем примере дефолт переопределен - public B() {Console.Write("instanceA");}. Инициализация присутсвует.
refregIf an instance constructor has no constructor initializer, a constructor initializer of the form base() is implicitly provided. Thus, an instance constructor declaration of the form
C(...) {...}
is exactly equivalent to
C(...): base() {...}

Согласно спецификации может быть два варианта:
constructor_initializer
: ':' 'base' '(' argument_list? ')'
| ':' 'this' '(' argument_list? ')'

stut, есть спецификация языка, предлагаю начать с выражения new T(A) - https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/expressions#object-creation-expressions
и затем уже заканчивать конструкторами - https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/classes#instance-constructors
...
Рейтинг: 0 / 0
Порядок инициализации конструкторов в c#
    #39511099
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У меня так получилось:
Код: plaintext
1.
2.
3.
static A()
static B()
A()
B()
Исходник
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
namespace ConsoleApplication1
{
	class A {
		public static int x;

		static A() {
			Console.WriteLine("static A()");
		}

		public A() {
			Console.WriteLine("A()");
		}
	}


	class B : A {
		static B() {
			x = 0;
			Console.WriteLine("static B()");
		}

		public B() {
			Console.WriteLine("B()");
		}
	}

    class Program
    {
        static void Main()
        {
			B b = new B();
        }
    }
}

...
Рейтинг: 0 / 0
Порядок инициализации конструкторов в c#
    #39511126
Фотография LR
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TУ меня так получилось:
Все согласно сказанному выше
Код: c#
1.
2.
3.
4.
5.
6.
	class B : A {
		static B() {
			//x = 0;
			Console.WriteLine("static B()");
			x = 0;
		}


До кучи - https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/classes#static-constructors
...
Рейтинг: 0 / 0
Порядок инициализации конструкторов в c#
    #39511137
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LRDima TУ меня так получилось
На моей памяти - не поверите, но я трезвый был - человеку удавалось получить инстанс класса Math. Там да, были те еще изввраты с рефлекшеном, но ... это совсем не те практики для нормального программирования.
...
Рейтинг: 0 / 0
Порядок инициализации конструкторов в c#
    #39511216
Фотография LR
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры Павловны,
наверное это был какой-нить MyTrick.Math (а не System.Math)?

Совсем не в тему, прошу прощения, но, глянув исходники Math , озадачился: почему doubleRoundLimit объявлено как static, а maxRoundingDigits - как const? Почему не одинаково? Оно, наверное, и не принципиально, но порождает недопонимание...
...
Рейтинг: 0 / 0
25 сообщений из 39, страница 1 из 2
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Порядок инициализации конструкторов в c#
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]