С наступающим Новым годом! Форум программистов, компьютерный форум, киберфорум
Наши страницы
C# для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.89/9: Рейтинг темы: голосов - 9, средняя оценка - 4.89
DPW
97 / 97 / 15
Регистрация: 23.05.2012
Сообщений: 259
1

Структуры против Классов

19.07.2013, 14:06. Просмотров 1611. Ответов 30
Метки нет (Все метки)

C# - язык 100% объектно-ориентированный. Основное детище ООП - класс.
Уважаемые форумчане,
Подскажите, пожалуйста, примеры практической реализации, когда использование структур в C# единственно возможно или предпочтительно.
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
19.07.2013, 14:06
Ответы с готовыми решениями:

Реализация структуры классов
Прошу помощи в реализации данной структуры классов.

Переделать программу из классов в структуры
using System; using System.Collections.Generic; using System.ComponentModel;...

Структуры. Можно ли наследовать как от абстрактных классов?
я тут немного почитал о структурах и понял следующее: они свои объекты...

Разработать систему классов по заданной теме. Обеспечить соответствующую функциональность классов
Блин, люди, помоги с задачей :( А то зачет не поставят :( Разработать...

Массив разных классов. Как добратся до всех полей этих классов?
Все классы имеют общего предка. Экземпляры этих классов запихнуты в один...

30
Smems
149 / 148 / 29
Регистрация: 21.05.2010
Сообщений: 338
19.07.2013, 14:15 2
DPW, структура занимает меньше памяти. Лучше использовать вместо "маленьких" классов. Например:

C#
1
2
3
4
5
struct Point
{
    int X;
    int Y;
}
менее затратно, нежели

C#
1
2
3
4
5
class Point
{
    int X;
    int Y;
}
2
dev-a1056
228 / 95 / 27
Регистрация: 16.04.2013
Сообщений: 315
Записей в блоге: 2
19.07.2013, 14:20 3
почитай про различия класса (reference type) и структуры (value-type).

Добавлено через 1 минуту
Цитата Сообщение от Smems Посмотреть сообщение
структура занимает меньше памяти. Лучше использовать вместо "маленьких" классов. Например:
, тебя походу это тоже касается.
0
DPW
97 / 97 / 15
Регистрация: 23.05.2012
Сообщений: 259
19.07.2013, 14:30  [ТС] 4
Уважаемые форумчане,
и dev-a1056, эта тема выросла из множества уже обсужденного на этом и не только форуме.

Вопрос не в том в чем отличие, а в том как использовать

Все уже прочитали и про значимые и про ссылочные и про ссылки внутри значимых и наоборот
Эту тема я поднял, чтоб усилиями сообщества создать "коллекцию" практических примеров где без структур не обойтись.
Убедительно прошу воздержаться от цитирования учебников, если по существу вопроса написать нечего.

dev-a1056, если в своей практике вы обдуманно использовали структуры и они облегчили Вам жизнь я с радостью... да думаю и многие начинающие программисты, с удовольствием примем ваш совет и пример
0
dev-a1056
228 / 95 / 27
Регистрация: 16.04.2013
Сообщений: 315
Записей в блоге: 2
19.07.2013, 14:44 5
DPW, так вот я тебе еще раз говорю, что ты ни чего не понял в отличиях класса и структуры, если благодаришь того, кто заведому херню написал. Если бы понял (+ boxing/unboxing), то вопроса бы такого не возникло вообще.
0
Smems
149 / 148 / 29
Регистрация: 21.05.2010
Сообщений: 338
19.07.2013, 14:44 6
dev-a1056, читай: Использование структур (Руководство по программированию на C#)
0
dev-a1056
228 / 95 / 27
Регистрация: 16.04.2013
Сообщений: 315
Записей в блоге: 2
19.07.2013, 14:52 7
Smems, ты уверен, что понял эту статью? Если да, то выражаться стоит яснее. Хотя, это все бисер перед свиньями.
0
DPW
97 / 97 / 15
Регистрация: 23.05.2012
Сообщений: 259
19.07.2013, 14:57  [ТС] 8
Тяжкое начало, попробую сам.
Признавая заслуги форумчан turbanoff'а и Psilon'а в нелегком деле поиска истины

Метод GetEnumerator() коллекций List и Dictionary
всегда возвращает структуру (экземпляр итератора), содержащую указатель на текущий элемент списка.
Без неё здесь никуда.

А вы какие примеры знаете?
0
Spectral-Owl
576 / 554 / 155
Регистрация: 29.06.2010
Сообщений: 1,588
Завершенные тесты: 1
19.07.2013, 17:58 9
Как для примера думаю сгодится сравнение структуры Color и класса Image в качестве их свойств (ForeColor и BackgroundImage соответственно) объектов класса Button:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
        private void Method() //присваивает объекту button2 значения свойств объекта button1
        {
            button2.ForeColor = button1.ForeColor;
            button2.BackgroundImage = button1.BackgroundImage;
        }
 
        private void Method_ChangeColor()
        {
            button1.ForeColor = Color.White; //изменение цвета шрифта первой кнопки. вторая осталась без изменений
        }
 
        private void Method_ChangeImage()
        {
            button1.BackgroundImage.RotateFlip(RotateFlipType.Rotate270FlipNone);
            //изменение изображения на первой кнопке (разворот чёрт-куда). 
            //картинка на второй кнопке изменяется соответственно. 
            //(вот только чтоб заметить это надо как минимум навести указатель на кнопку, или ещё каким образом вызвать перирисовку)
        }
такой вод простенький примитивчик)
2
turbanoff
Эксперт Java
4020 / 3755 / 742
Регистрация: 18.05.2010
Сообщений: 9,329
Записей в блоге: 11
Завершенные тесты: 1
19.07.2013, 19:47 10
Структуры, насколько я знаю, введены для двух целей:
1. Повышение производительности
2. Упрощение работы с нативным кодом.
0
Psilon
Master of Orion
Эксперт .NET
6013 / 4866 / 902
Регистрация: 10.07.2011
Сообщений: 14,477
Записей в блоге: 5
Завершенные тесты: 4
19.07.2013, 19:59 11
turbanoff, 3. когда в качестве поведения по-умолчанию нужно чтобы происходило именно копирование, а не присваивание ссылки. В отличие от авторов CLR, мы не можем переопределить оператор '=' для наших классов.
0
turbanoff
Эксперт Java
4020 / 3755 / 742
Регистрация: 18.05.2010
Сообщений: 9,329
Записей в блоге: 11
Завершенные тесты: 1
19.07.2013, 20:05 12
Psilon, копирование - не есть сама цель введения структур. С точки зрения программиста, это не является каким-то сложным действием, которое нельзя повторить с помощью классов.
Цитата Сообщение от Psilon Посмотреть сообщение
В отличие от авторов CLR, мы не можем переопределить оператор '=' для наших классов.
Кроме C# есть и другие языки программирования для .NET, в которых вы можете опеределить '=' для наших классов.
0
Psilon
Master of Orion
Эксперт .NET
6013 / 4866 / 902
Регистрация: 10.07.2011
Сообщений: 14,477
Записей в блоге: 5
Завершенные тесты: 4
19.07.2013, 20:08 13
turbanoff, ну VB я не беру в расчет
, тот же шарп, только синтаксис иной. А про MC++ забыл
Цитата Сообщение от turbanoff Посмотреть сообщение
копирование - не есть сама цель введения структур.
не цель, но одна из. Логика, являются ли два объекта разными или это один и тот же объект - достаточно важна. И тут не важно переопределение Equals и пр.
0
turbanoff
19.07.2013, 22:17
  #14

Не по теме:

Цитата Сообщение от Psilon Посмотреть сообщение
не цель, но одна из.
Копирование структур - это не то, чего нельзя достичь с помощью классов, и не то для чего они были сделаны. Копирование ради копирования не имеет смысла.
Вы смешиваете цели и способы получения/последствия этих целей. Копирование при присваивании - не цель.

1
DPW
97 / 97 / 15
Регистрация: 23.05.2012
Сообщений: 259
20.07.2013, 14:34  [ТС] 15
Если без VB и MC++, то и в C# есть инструменты для создания копий экземпляров класса.
Метод ICloneable.Clone() реализуют достаточно большое число классов .NET
для собственных классов и не только никто не отменял конструктор копирования public MyClass(MyClass mc)
Я сомневаюсь, что копирование полей или на худой конец unsafe побитовое/байтовое копирование структуры данных класса создаст машинный код сильно отличающийся от того что происходит при присваивании значимых типов.

Давайте вернемся чуть выше.
turbanoff, вы написали что структуры используются для повышения производительности.
Аргумент повышения производительности - бесспорно, железный
Вы не могли бы пояснить в чем конкретно и как это работает.

MSDN пишет так,
Тип struct подходит для создания несложных объектов, таких как Point, Rectangle и Color. Хотя точку удобно представить в виде класса с автоматически реализуемыми свойствами, в некоторых сценариях структура может оказаться более эффективной. Например, при объявлении массива из 1000 объектов Point потребуется выделить дополнительную память для хранения ссылок на все эти объекты, и структура в таком случае будет более экономичным решением.
C#
1
2
3
4
5
6
7
8
9
10
public struct CoOrds
{
    public int x, y;
 
    public CoOrds(int p1, int p2)
    {
        x = p1;
        y = p2;
    }
}
Поправьте меня, если я в чем-то ошибаюсь:
Для простых - да, логика на лицо. В приведенном выше примере Point расходует 4*2=8 байт.
Ссылка/адрес - еще (пусть) 8 байт.
8+8=16

ИТОГО: затраты на хранение массива экземпляров класса аж 16/8=2 раза больше чем на структуры

Но если структура 100, 200, и т.д. байт?
(Х+16)/Х при растущем размере структуры эта прибавка превращается в ничто.
0
Psilon
Master of Orion
Эксперт .NET
6013 / 4866 / 902
Регистрация: 10.07.2011
Сообщений: 14,477
Записей в блоге: 5
Завершенные тесты: 4
20.07.2013, 15:35 16
DPW,
Если без VB и MC++, то и в C# есть инструменты для создания копий экземпляров класса.
Метод ICloneable.Clone() реализуют достаточно большое число классов .NET
для собственных классов и не только никто не отменял конструктор копирования public MyClass(MyClass mc)
Я сомневаюсь, что копирование полей или на худой конец unsafe побитовое/байтовое копирование структуры данных класса создаст машинный код сильно отличающийся от того что происходит при присваивании значимых типов.
http://stackoverflow.com/questions/536349/why-no-icloneablet
ICloneable is considered a bad API now, since it does not specify whether the result is a deep or a shallow copy.
где-то видел пост от самих МС, которые не советуют юзать ICloneable. Что касается конструкторов копирования, то в отличие от плюсов они не реализуются по-умлочанию, а для каждого класса городить свой - затруднительно, особенно когда полей (особенно приватных) много.
Поправьте меня, если я в чем-то ошибаюсь:
Для простых - да, логика на лицо. В приведенном выше примере Point расходует 4*2=8 байт.
Ссылка/адрес - еще (пусть) 8 байт.
8+8=16
ссылка - 4 байта, так как приложения запускаются в 32-песочнице.
ИТОГО: затраты на хранение массива экземпляров класса аж 16/8=2 раза больше чем на структуры

Но если структура 100, 200, и т.д. байт?
(Х+16)/Х при растущем размере структуры эта прибавка превращается в ничто.
вопрос не в затратах на хранение, а то, что структуры как правило хранятся в стеке, а не в куче, выделение памяти в стеке ничего не стоит, а вот в куче... Когда создается и удаляется 100000 объектов в секунду, то разница в производительности будет радикальная, особенно из-за фрагментации кучи и работы GC. Ну и про box/unbox нельзя забывать
0
Wolfdp
868 / 778 / 202
Регистрация: 15.06.2012
Сообщений: 3,051
Записей в блоге: 1
Завершенные тесты: 1
20.07.2013, 16:08 17
Цитата Сообщение от Psilon Посмотреть сообщение
вопрос не в затратах на хранение, а то, что структуры как правило хранятся в стеке, а не в куче, выделение памяти в стеке ничего не стоит, а вот в куче... Когда создается и удаляется 100000 объектов в секунду, то разница в производительности будет радикальная, особенно из-за фрагментации кучи и работы GC. Ну и про box/unbox нельзя забывать
Оказывается я ничего не знаю про шарп... Как я понял, происходит нечто следующее: при работе со структурой, мы сразу тянем значение из стека. При работе с классом, мы сначала тянем адрес объекта из стека, переходим по адресу в кучу и уже тянем данные из кучи. Ну и плюс, куча чиститься не так активно, как стек.

Или я написал полную хНЮ?
0
serefa
50 / 43 / 4
Регистрация: 07.10.2010
Сообщений: 95
20.07.2013, 16:41 18
Ага. Полную фигню.
В стеке хранятся адреса параметров функций и локальных переменных. Не важно reference type или value type.
По адресу value type лежит значение, по адресу reference type - ссылка на значение в куче.

А вот поля классов лежат в куче. Следовательно, даже если тип нашего поля будет value type, оно все равно будет лежать в куче.
0
DPW
97 / 97 / 15
Регистрация: 23.05.2012
Сообщений: 259
20.07.2013, 17:01  [ТС] 19
Wolfdp, да все правильно.
На это я обратил внимание когда предыдущий ответ писал.

Правда хотел пока тему стека обойти.
Естественно (сделайте скидку на точности в машинных командах от 8080), стек он побыстрее
pop и push команды выполняющиеся за один машинный цикл
LD A,(HL) естественно за 3.

Но так ли оно сейчас? Где в процессорах куча контроллеров предварительной обработки кода, упорядочивателей предсказателей и т.д. Ну и естественно кэш - это далеко не RAM.
Прежде чем лезть в эти дебри, хочется с предыдущим разобраться.

Отступление не про стек но похоже:
в С++ помниться короткие методы рекомендовалось делать inline чтоб из-за маленькой хрени переходы (jp) не делать.

Psilon, определенно ICloneable нравиться не всем (наследование тому веская причина), но в тех классах где он есть - поверь он там не просто так и работает как ожидается.

Цитата Сообщение от Psilon Посмотреть сообщение
ссылка - 4 байта, так как приложения запускаются в 32-песочнице.
Вот определенно тебе второе журфака образование надо. Ты так классно цитатами пользуешься. Тот абзац имел цельный смысл (зависит от песочницы), но 50% 100% прирост это не 0.1%, это все равно до фига.

Ну и прежде чем окунуться в стеки, объясни пожалуйста,
куча факт фрагментирована, т.к. память выделяется по принципу где нашлась.
Но в распределении памяти структура и класс одинаковы. Так уж они развивались. Все данные идут по-порядку.
Не будет он одно поле в начало другое в конец писать. Или здесь принципиальная ошибка.

И второй вопрос:
Цитата Сообщение от Psilon Посмотреть сообщение
Когда создается и удаляется 100000 объектов в секунду
- А не в том ли суть классов чтоб не создавать и удалять n! объектов в секунду, а раз создать и использовать.
Нафиг тогда ООПвообще если это заведомо тормозной путь. ОНИ же не дурачье.
- В том же С++ классы спокойно жили в "стеке" и без динамической памяти и указателей. Но в C# их под одну гребенку в кучу отправили. ОНИ же не дурачье.

Может все-таки среда CLR как-то по другому организована и в ней эти накладные расходы минимизированы.

Добавлено через 2 минуты
serefa, т.е мы и пришли к тому что стек в C# и стек в С++ это таки одинаковые понятия только в названии?

Добавлено через 59 секунд
Цитата Сообщение от serefa Посмотреть сообщение
Следовательно, даже если тип нашего поля будет value type, оно все равно будет лежать в куче.
Это естественно
0
Anklav
443 / 301 / 47
Регистрация: 23.01.2013
Сообщений: 641
Завершенные тесты: 2
20.07.2013, 17:45 20
Цитата Сообщение от DPW Посмотреть сообщение
Ну и прежде чем окунуться в стеки, объясни пожалуйста,
куча факт фрагментирована, т.к. память выделяется по принципу где нашлась.
Но в распределении памяти структура и класс одинаковы. Так уж они развивались. Все данные идут по-порядку.
Не будет он одно поле в начало другое в конец писать. Или здесь принципиальная ошибка.
В C# сборщик мусора дефрагментирует(для чего же и нужны всякие fixed и GCHanlde) память(если после сборки мусора фрагментация велика) таким образом, что бы все данные лежали в 1 куче.

Есть внутренний указатель (nextObjPtr), который указывает на конец кучи.
Как осуществляется выделение памяти:
1) Начиная с этого указателя необходимая объекту память очищается.
2) Вызывается конструктор.
3) Как результат возвращается nextObjPtr
4) nextObjPtr перемещается в конец созданного объекта.

Ну и + перед выделением памяти проверяется есть ли свободная память. Если ее не достаточно запускается полная сборка мусора, если памяти не достаточно и после нее, то выкидывается исключение. И про поколения я не писал.

Добавлено через 10 минут
Да и про структуры, не нужно привязываться к стеку, данные находятся там если их туда насильно положить (stackalloc) или если объявить в методе. (возможно забыл что то еще)

Скажем так: есть некая сущность(стек, класс, структура) в которой объявлена структура/класс. Если это структура, то она полностью находится в данной сущности, а если это класс то в сущности находится ссылка на объект лежащий где то в куче.
1
20.07.2013, 17:45
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.07.2013, 17:45

Сериализация списка классов (нескольких классов)
Ув. форумчане. Знаю, что данный вопрос неоднократно поднимался и здесь...

C# против VB.NET
На многих форумах в последнее время я встречаю рассуждения программистов (и...

XmlDocument против Dictionary и List
Сразу к сути: В классе используются var dic = new Dictionary<string,...


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

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

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