В статье «Классы или структуры, в чем отличия» приведены небольшие примеры, которые, как показал опыт общения с начинающими программистами, недостаточны для более глубокого понимания этих различий. Поэтому будет полезно рассмотреть еще примеры.
Ключевое слово здесь, как предлагает в комментариях Руслан, альтернатива (структура или класс), т.е. когда что выбирать. Рекомендую обязательно эксперименты проводить в среде VS (не теоретически — лучше поймете!).
Эксперимент №1.
Для быстрого анализа в тексте примера 1 (файл Class2.cs) заменим только строку public class MFC на public struct MFC и запустим проект.
Получим 6 сообщений об ошибках:
Ошибка CS0106 Модификатор "virtual" недопустим для этого элемента. Ошибка CS0106 Модификатор "virtual" недопустим для этого элемента. Ошибка CS0106 Модификатор "virtual" недопустим для этого элемента. Ошибка CS0666 '"MFC.mother": новый защищенный член объявлен в структуре. Ошибка CS0666 '"MFC.father": новый защищенный член объявлен в структуре. Ошибка CS0666 '"MFC.child": новый защищенный член объявлен в структуре.
Анализ:
1) Первые три ошибки связаны с объявлением методов GetChild(), Output(), Tir() как virtual.
Вывод: модификатор virtual к методам структур не применим. Тем не менее, модификатор public имеет в структуре то же назначение, что и в классе — обеспечить доступ к данным.
2) Другие три ошибки связаны с объявлением в нашей структуре MFC полей mother; father; child с модификатором protected (в классе мы их так объявили, так как предполагали их защиту и наследование, см. Пример 2).
Вывод: Удалим модификатор protected, тем самым тип этих полей станет private (по умолчанию). Конечно, можно было бы явно вместо protected указать public, однако это будет неверно с позиций защиты данных.
Удалим лишнее, тогда получим в файле Class2.cs:
// структура вместо класса using System; namespace МатьОтецРебенок { // Инкапсуляция в структуре MFC public struct MFC { string mother; string father; string child; public MFC(string m, string f, string c) { mother = m; father = f; child = c; } // возврат имени ребенка public string GetChild() { return child; } // вывод имен членов семьи public void Output() { Console.WriteLine("Mать: " + mother + " отец: " + father); Console.WriteLine("Ребенок: " + child); } // Рисование разграничительной линии (пригодится) public void Tir() { Console.WriteLine("_____________________________"); } } }
Текст файла Program.cs оставим без изменений:
using System; namespace МатьОтецРебенок { class Program { static void Main() { // R - экземпляр MFC R = new MFC("Барбара", "Борис", "Бэлла"); R.Output(); R.Tir(); // разделитель информации // Дети и фамилия Console.WriteLine("Дети: " + R.GetChild()); R.Tir(); } } }
Результат:
Mать: Барбара отец: Борис Ребенок: Бэлла _____________________________ Дети: Бэлла _____________________________
В точном соответствии с Примером 1 на базе класса MFC. При необходимости разберите его отдельно.
Эксперимент 2.
Что произойдет, если мы удалим (удобнее просто пока закомментировать) конструктор public MFC(string m, string f, string c) { }.
Результат компиляции:
Ошибка CS1729 'MFC" не содержит конструктор, который принимает аргументы 3.
Конечно понятна причина, в Main() имеется оператор MFC R = new MFC(«Барбара», «Борис», «Бэлла»);, предполагающий создание экземпляра структуры с конкретными значениями полей.
Если так нельзя, то попробуем задать для структуры конструктор без параметров, например такой:
public MFC() { mother = "M"; father = "F"; child = "C"; }
Примечание. Конечно, особого смысла такой конструктор с постоянными полями не имеет, но нам важно понять отличия структуры от класса.
Соответственно в Main() оператор MFC R = new MFC(«Барбара», «Борис», «Бэлла»); заменим на MFC R = new MFC();.
Результат компиляции:
Ошибка CS0568 Структуры не могут содержать явных конструкторов без параметров.
Вывод 1: Для структур нельзя создать конструктор по умолчанию (без параметров).
А если выполнить обратную замену? Вместо struct напишем снова class? Тогда все замечательно, ошибок нет, результат проверки:
Mать: M отец: F Ребенок: C _____________________________ Дети: C _____________________________
Вывод 2: Для класса создание конструктора без параметров вполне допустимо.
Эксперимент №3.
Если в последнем случае (с классом) вообще удалим конструктор класса MFC. Тогда при выполнении оператора MFC R = new MFC(); объект будет все таки создан, но с пустыми полями (так как они типа string, то их значения = null). И вот результат:
Mать: отец: Ребенок: _____________________________ Дети: _____________________________
Вывод. Если конструктор в описании класса отсутствует, то он по умолчанию все таки создается, равно как и полям объекта присваиваются начальные значения.
Итоги экспериментов:
- Замена структуры на класс происходит без особых проблем, однако при замене класса структурой могут возникать ошибки.
- Использование структур исключает наследование. Совет: Если Вы четко определились с конструкцией данных — используйте структуры, иначе — классы.
- Структура не может содержать явного конструктора без параметров, однако он уже существует по умолчанию.
- Создание конструктора класса без параметров вполне допустимо.
- При отсутствии конструктора в описании класса он создается по умолчанию.
Сравните эти выводы с таблицей, где сравниваются классы и структуры, см. «Классы или структуры, в чем отличия».
NEW: Наш Чат, в котором вы можете обсудить любые вопросы, идеи, поделиться опытом или связаться с администраторами.
В этом небольшом уроке мы поговорим об альтернативе классам — структурах. Структура – это более простая версия классов. Все структуры наследуются от базового класса
Руслан! Я понимаю, что Вы торопите меня раскрыть тему. Спасибо. Насчет наследования структур от базового класса — подумаю.