Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.54/13: Рейтинг темы: голосов - 13, средняя оценка - 4.54
Alvin Seville
332 / 265 / 131
Регистрация: 25.07.2014
Сообщений: 4,537
Записей в блоге: 9
1

Инициализация полей структур

11.10.2018, 16:00. Просмотров 2471. Ответов 45
Метки нет (Все метки)

Насколько знаю, у экземпляров классов поля всегда инициализируются значениями по умолчанию перед тем как в дело вступает конструктор. Почему у структур для инициализации полей используется конструктор по умолчанию для этих целей?
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
11.10.2018, 16:00
Ответы с готовыми решениями:

Инициализация массива структур
суть в чем. есть структура SS полем которой является матрица S. есть массив x - содержащий 8...

Инициализация структуры содержащей массив структур
Всем привет. на с# только начал писать, и нужно перенести сишный код в котором было несколько...

Не происходит инициализация полей
есть класс public class DinnerParty { private const int costOfFoodPerPerson = 30; ...

Инициализация полей классов
Сколько раз здесь будет инициализирован x? class InitialierTestClass { public...

45
Эксперт .NET
14697 / 11111 / 2919
Регистрация: 17.09.2011
Сообщений: 18,650
11.10.2018, 20:33 41
Цитата Сообщение от Cupko Посмотреть сообщение
Но как бэ все равно никакой дефолтный конструктор не вызывается.
Так это же скомпилированный код.
Если разговор о C#, то конструктор-то есть. Как там его компилятор обработает в целях оптимизации — это его дело, в конце-концов все превратится в ассемблер, где вообще без конструкторов
1
604 / 558 / 164
Регистрация: 17.07.2012
Сообщений: 1,592
Записей в блоге: 1
11.10.2018, 20:42 42
kolorotur,
Так у меня какой-то диссонанс от таких оптимизаций
Я реально полагал что из шарпа вызвать конструктор явно нельзя. По той простой причине, что ему нечего инициализировать.
Т.е. в языке есть явный запрет на создание таких конструкторов, но нет запрета на вызов. А если учесть то, что он нигде не нужен (да и по факту, в MSIL, нигде и не вызывается), то вопрос "Зачем?", заданный выше, у меня тоже возникает.
0
Эксперт .NET
14697 / 11111 / 2919
Регистрация: 17.09.2011
Сообщений: 18,650
11.10.2018, 21:04 43
Цитата Сообщение от Cupko Посмотреть сообщение
Так у меня какой-то диссонанс от таких оптимизаций
Вам надо пару лет на плюсах поработать — прививка от диссонансов на всю жизнь, т.к. после оптимизаций плюсового компилятра уже ничего не удивит

Цитата Сообщение от Cupko Посмотреть сообщение
в языке есть явный запрет на создание таких конструкторов, но нет запрета на вызов.
Так явный запрет на изменение его реализации, а в наличии он всегда.
Именно для уменьшения сюрпризов: переменная проинициализирована без вызова конструктора с параметрами (правила это позволяют), хотя другого не определено. Как так?!

Цитата Сообщение от Cupko Посмотреть сообщение
А если учесть то, что он нигде не нужен (да и по факту, в MSIL, нигде и не вызывается), то вопрос "Зачем?"
В смысле "нигде"?
Вы не сможете использовать переменную значимого типа без явной инциализации всех членов или без вызова конструктора — вот тут и нужен.
C#
1
2
3
4
5
6
7
8
9
10
11
struct Foo
{
   public int x;
   public string y;
}
 
void Bar()
{
   Foo foo;
   Console.WriteLine(foo.x); // Ататат, переменная foo не проинициализирована!
}
В примере выше чтобы избежать ошибки компиляции у вас есть два варианта:
1. Явно проинициализировать все члены перед первым использованием:
C#
1
2
3
4
5
Foo foo;
foo.x = 42;
foo.y = "Hello world!";
 
Console.WriteLine(foo.x); // OK
2. Вызвать дефолтный конструкор:
C#
1
2
Foo foo = new Foo();
Console.WriteLine(foo.x); // ОК
Второй вариант зачастую намного проще.
2
604 / 558 / 164
Регистрация: 17.07.2012
Сообщений: 1,592
Записей в блоге: 1
11.10.2018, 21:36 44
kolorotur, спасибо, конечно, за примеры, но пока ничего логичнее не стало. Надо на досуге почитать/поэкспериментировать.
Все равно смахивает на какой-то очередной костыль. "чтобы избежать ошибки компиляции", как вы говорите
0
1108 / 779 / 219
Регистрация: 15.08.2010
Сообщений: 2,159
11.10.2018, 22:15 45
Итак, провел небольшой тест с подменой понятий dll. Вот результат. Что с ним делать я понятия не имею

для начала если добавить в конструктор вывод в консоль и скомпилить с этой библиотекой. (тестовый код ниже приведен)
Кликните здесь для просмотра всего текста
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
Declaring local variable
 
Boxing
 
Lib.Structure
 
new Structure() - set local variable
Oddity constructor called
 
Create instance of Test - contains instance variable
 
new Structure() - set instance field
Oddity constructor called
 
new Structure() - set static field
Oddity constructor called
 
new Structure[10]
 
Passing argument to method
 
default(T) in generic method with new() constraint
 
new T() in generic method with new() constraint
Oddity constructor called
 
default(T) in generic method with struct constraint
 
new T() in generic method with struct constraint
 
Activator.CreateInstance(typeof(Structure))
 
Activator.CreateInstance<Structure>()


Далее я решил просто выставить значение i на 987 в конструкторе без параметров и потом выводить именно это значение.

Тестовый код:
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
namespace Lib
{
    public struct Structure
    {
        public int i;
    }
}

Кликните здесь для просмотра всего текста
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
using System;
using System.Runtime.CompilerServices;
using Lib;
 
namespace Test
{
    internal class Test
    {
        private static Structure staticField;
        private Structure instanceField;
 
        private static void Main()
        {
            Structure localDeclarationOnly;
            localDeclarationOnly.i = 2;
            Report("Declaring local variable", localDeclarationOnly);
            
            // No variables within the value, so we can use it
            // without inializing anything
            
            object o = localDeclarationOnly;
            Report("Boxing", (Structure)o);
            
            // Just make sure it’s really done it
            Report(o.ToString());
 
            var local = new Structure();
            Report("new Structure() – set local variable", local);
            
            var t = new Test();
            Report("Create instance of Test – contains instance variable", t.instanceField);
            
            t.instanceField = new Structure();
            Report("new Structure() – set instance field", t.instanceField);
           
            staticField = new Structure();
            Report("new Structure() – set static field", staticField);
            
            var a = new Structure[10];
            Report("new Structure[10]", a[0]);
            
           
            MethodWithParameter(local);
 
            GenericMethod<Structure>();
            GenericMethod2<Structure>();
            Report("Activator.CreateInstance(typeof(Structure))", (Structure)Activator.CreateInstance(typeof(Structure)));
 
            Report("Activator.CreateInstance<Structure>()", Activator.CreateInstance<Structure>());
 
            Console.ReadKey();
        }
 
        [MethodImpl(MethodImplOptions.NoInlining)]
        private static void MethodWithParameter(Structure Structure)
        {
            Report("Passing argument to method", Structure);
        }
 
        private static void GenericMethod<T>() where T : new()
        {
            object t = default(T);
            Report("default(T) in generic method with new() constraint", (Structure)t);
            
            t = new T();
            Report("new T() in generic method with new() constraint", (Structure)t);
            
        }
 
        private static void GenericMethod2<T>() where T : struct
        {
            object t = default(T);
            Report("default(T) in generic method with struct constraint", (Structure)t);
           
            t = new T();
            Report("new T() in generic method with struct constraint", (Structure)t);
           
        }
        private static void Report(string text)
        {
            Console.WriteLine();
            Console.WriteLine(text);
        }
 
        private static void Report(string text, Structure s)
        {
            Console.WriteLine();
            Console.WriteLine(text);
            Console.WriteLine(s.i);
        }
    }
}


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

1. Честная либа без всяких переопределений (двойка в начале так и задумана)
Кликните здесь для просмотра всего текста
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
Clean
 
Declaring local variable
2
 
Boxing
2
 
Lib.Structure
 
new Structure() - set local variable
0
 
Create instance of Test - contains instance variable
0
 
new Structure() - set instance field
0
 
new Structure() - set static field
0
 
new Structure[10]
0
 
Passing argument to method
0
 
default(T) in generic method with new() constraint
0
 
new T() in generic method with new() constraint
0
 
default(T) in generic method with struct constraint
0
 
new T() in generic method with struct constraint
0
 
Activator.CreateInstance(typeof(Structure))
0
 
Activator.CreateInstance<Structure>()
0

2. Компиляция с подмененной dll
Кликните здесь для просмотра всего текста
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
Compiled with declared default
 
Declaring local variable
2
 
Boxing
2
 
Lib.Structure
 
new Structure() - set local variable
987
 
Create instance of Test - contains instance variable
0
 
new Structure() - set instance field
987
 
new Structure() - set static field
987
 
new Structure[10]
0
 
Passing argument to method
987
 
default(T) in generic method with new() constraint
0
 
new T() in generic method with new() constraint
987
 
default(T) in generic method with struct constraint
0
 
new T() in generic method with struct constraint
0
 
Activator.CreateInstance(typeof(Structure))
0
 
Activator.CreateInstance<Structure>()
0

3. Компилячия с честрой либой, потом подмена ее на фейковую
Кликните здесь для просмотра всего текста
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
replaced
 
Declaring local variable
2
 
Boxing
2
 
Lib.Structure
 
new Structure() - set local variable
0
 
Create instance of Test - contains instance variable
0
 
new Structure() - set instance field
0
 
new Structure() - set static field
0
 
new Structure[10]
0
 
Passing argument to method
0
 
default(T) in generic method with new() constraint
0
 
new T() in generic method with new() constraint
987
 
default(T) in generic method with struct constraint
0
 
new T() in generic method with struct constraint
0
 
Activator.CreateInstance(typeof(Structure))
0
 
Activator.CreateInstance<Structure>()
0

4. Если компилить с 987 и потом подменить на честную, бросит эксепшн что конструктор не определен

В архиве прилагаю собранные честную и 987 либы. Можно переименовать в Lib.dll и скомпилить с тестом
1
Вложения
Тип файла: zip Struct.zip (6.8 Кб, 0 просмотров)
Модератор
8666 / 5991 / 1699
Регистрация: 21.04.2018
Сообщений: 17,810
Записей в блоге: 2
11.10.2018, 22:27 46
Цитата Сообщение от КОП Посмотреть сообщение
Итак, провел небольшой тест с подменой понятий dll. Вот результат. Что с ним делать я понятия не имею

Аплодирую Вашей настойчивости в поисках неизвестно чего!
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
11.10.2018, 22:27

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

Инициализация статических полей
Ковыряю legacy код, возможно нубский вопрос:( Есть глобальный класс со статическими полями и...

Инициализация полей структуры
Всем, привет. Такой вопрос, при написании вот такого кода в c# struct a { } int main() { ...

Обращение и инициализация полей класса
привет! помогите пожалуйста разобраться, как это работает. нужно понять что просходит под...

Инициализация в классе полей типа Enum
Добрый день! Есть класс, в нем есть поле перечисления. class Worker { private string...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
46
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.