Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Свойства, доступные только для чтения и только для записиСодержание книги
Похожие статьи вашей тематики
Поиск на нашем сайте
Существует возможность создать свойство, доступное только для чтения, просто исключая set из определения свойства. То есть, чтобы сделать свойство Name из предыдущего примера доступным только для чтения, необходимо поступить следующим образом: private string name; public string Name { get { return name; } } Точно так же можно определить свойство, доступное только для записи, если исключить определение get. Однако это считается плохой практикой программирования, поскольку может ввести в заблуждение авторов клиентского кода. Вообще говоря, если возникает искушение поступить так, то лучше вместо свойства использовать метод. Модификаторы доступа для свойств Язык С# допускает применение различных модификаторов доступа для средств set и get свойств. Это дает возможность свойству иметь общедоступный get и приватный или защищенный set, и управлять тем, как и когда свойство может быть установлено. В следующем примере кода обратите внимание, что set имеет модификатор приватного доступа (private), a get - не имеет никакого. В этом случае get получает уровень доступа самого свойства. Одно из средств доступа - set или get - должно иметь уровень доступа свойства. Если get также будет иметь ассоциированный с ним защищенный уровень доступа, то компилятор сгенерирует ошибку, поскольку в этом случае и set, и get получают уровень доступа, отличающийся от уровня доступа самого свойства. public string Mame { get { return _name; } private set { _name = value; } } Автоматически реализуемые свойства Если наличие какой-либо логики в методах set и get свойства не предполагается, можно использовать автоматически реализуемые свойства. Такие свойства создают поддерживающие их переменные-члены автоматически. Код ранее приведенного примера с Age выглядел бы следующим образом: public int Age (get; set;} В объявлении private int age; нет необходимости — компилятор создаст его автоматически. При использовании автоматически реализуемых свойств проверка достоверности свойства не может быть выполнена в его методе set. Поэтому в предыдущем примере мы бы не смогли проверить корректность установки возраста. Также должны присутствовать оба метода доступа. То есть, попытка сделать свойство доступным только для чтения вызовет ошибку: public int Age (get;) Однако уровень доступа каждого метода доступа может быть различным. Поэтому следующий код является допустимым: public int Age (get; private set; }
Замечание о встраивании Некоторые разработчики могут быть обеспокоены тем, что в предыдущих разделах демонстрируется множество ситуаций, когда стандартная практика кодирования С# порождает множество очень маленьких функций - например, для доступа к полю через свойство вместо непосредственного обращения к нему. Не повлияет ли это на производительность из-за накладных расходов, связанных с дополнительными вызовами функций? Ответ состоит в том, что не нужно беспокоиться о потере производительности по причине такой методологии программирования на С#. Вспомните, что код С# транслируется в IL, а затем JIT компилирует его во время выполнения в родной исполняемый код. JIT-компилятор спроектирован так, что генерирует высоко оптимизированный код и без колебаний использует встроенный (inline) код там, где это необходимо (т.е. заменяет вызовы функций встроенным кодом). Метод или свойство, чья реализация просто вызывает другой метод или возвращает поле, почти наверняка будет преобразован во встроенный код. Однако следует отметить, что решение относительно встраивания принимает исключительно CLR. У вас нет никакой возможности управлять тем, какие методы будут встроенными - например, с помощью какого-то ключевого слова вроде применяемого в С++ inline. Конструкторы Синтаксис объявления базовых конструкторов выглядит как объявление метода, который имеет то же имя, что и включающий его класс, и не имеет никакого типа возврата: public class MyClass i { public MyClass () { } // остаток определения класса Предусматривать конструктор в классе не обязательно. И до сих пор это не делалось ни в одном из приведенных примеров. В общем случае, если никакого конструктора не определяется, то компилятор просто создаст конструктор по умолчанию "за кулисами". Это будет конструктор очень обобщенного вида, который просто инициализирует все поля-члены, обнуляя их (null-ссылки для ссылочных типов, 0 для числовых типов и false - для булевских). Часто это вполне адекватно; если же нет, то придется написать свой собственный конструктор. Конструкторы подчиняются тем же правилам перегрузки, что и обычные методы (т.е. public MyClass () // конструктор без параметров { //код конструктора } public MyClass(int number) // другая перегрузка { //код конструктора } Однако обратите внимание, что если вы применяете любой конструктор с параметрами, то в этом случае компилятор не генерирует никакого конструктора по умолчанию. Такой конструктор генерируется только тогда, когда ни одного конструктора явно не определено. В следующем примере, поскольку определен конструктор с одним параметром, компилятор предполагает, что это - единственный конструктор, который вы хотите сделать доступным, а потому не применяет никакого другого: public class MyNumber { private int number; public MyNumber(int number) { this.number = number; } } Этот код также иллюстрирует типичное использование ключевого слова this для того, чтобы отличать поля класса от параметров с теми же именами. Теперь, если попытаться создать экземпляр класса MyNumber с помощью конструктора без параметров, возникнет ошибка компиляции: MyNumber numb = new MyNumber (); //вызовет ошибку при компиляции Следует упомянуть также, что конструкторы можно объявлять приватными или защищенными - так, что они будут невидимыми коду других классов: public class MyNumber { private int number; private MyNumber(int number) // другая перегрузка { this.number = number; } } Этот пример на самом деле не определяет никакого общедоступного или даже защищенного конструктора для MyNumber. Это делает невозможным создание экземпляра данного класса внешним кодом с помощью операции new (хотя можно написать общедоступное статическое свойство или метод, в котором будет создаваться экземпляр класса). Это удобно в двух ситуациях: 1) если класс служит лишь контейнером для некоторых статических членов или свойств, а потому его экземпляры никогда не создаются; 2) если необходимо, чтобы экземпляры класса создавались только вызовом некоторой статической функции-члена (так называемый подход "фабрик классов" к созданию объектов). Статические конструкторы Одним из новых средств С# является возможность написания статических конструкторов класса без параметров. Такой конструктор выполняется лишь однажды, в противоположность всем описанным до сих пор конструкторам, которые были конструкторами экземпляров и выполнялись при каждом создании объектов классов. class MyClass { static MyClass () { // код инициализации } // остаток определения класса } Одной из причин для написания статического конструктора может быть наличие в классе некоторых статических полей или свойств, которые должны быть инициализированы внешним источником, прежде чем класс будет использован впервые. Исполняющая среда.NET не дает никаких гарантий того, что статический конструктор будет вызван, поэтому в него не следует помещать код, который должен быть выполнен в определенный момент (например, при загрузке сборки в память). Точно так же невозможно предсказать, в каком порядке будут выполнены статические конструкторы различных классов. Единственное, что гарантируется - это то, что статический конструктор будет запущен максимум один раз и что он будет вызван до любого первого обращения к данному классу. В С# статический конструктор обычно выполняется непосредственно перед первым вызовом любого члена класса. Обратите внимание, что статический конструктор не имеет никакого модификатора доступа. Он никогда не вызывается никаким другим кодом С#, а всегда только исполняющей средой.NET при загрузке класса, поэтому никакой модификатор доступа вроде public или private не имеет смысла. По той же причине статический конструктор не может принимать никаких параметров, и у каждого класса может быть только один статический конструктор. Должно быть очевидным также, что статический конструктор может иметь доступ только к статическим членам класса, но не членам экземпляра. Также следует отметить, что в классе допускается определять одновременно статический конструктор и конструктор экземпляра без параметров. Хотя их списки параметров идентичны, не возникает никакого конфликта, потому что статический конструктор выполняется во время загрузки класса, а конструктор экземпляра - при создании экземпляра, поэтому не происходит никакой путаницы с тем, когда какой конструктор вызывать. Кроме того, если есть более одного класса со статическим конструктором, то неизвестно, какой из статических конструкторов будет вызван первым. Поэтому в статический конструктор не должен помещаться код, который бы зависел от того, были или не были вызваны ранее другие статические конструкторы. С другой стороны, если любые статические поля должны иметь определенные значения по умолчанию, то они будут размещены, до вызова статического конструктора. Следующий пример иллюстрирует применение статического конструктора и основан на идее программы, имеющей некоторые пользовательские предпочтения (которые предварительно сохранены в конфигурационном файле). Для простоты предположим, что имеется только одно пользовательское предпочтение - значение BackColor, которое может представлять цвет фона, используемый приложением. И поскольку мы здесь не хотим погружаться в детали написания кода, читающего данные из внешнего источника, то предположим, что предпочтительный цвет фона - красный по будним дням и зеленый по выходным. Все, что должна делать программа - это отображать предпочтение в консольном окне. Этого будет достаточно, чтобы увидеть работу статического конструктора. namespace Wrox.ProCSharp.StaticConstructorSample { public class UserPreferences { public static readonly Color BackColor; static UserPreferences () { DateTime now = DateTime.Now; if (now.DayOfWeek == DayOfWeek.Saturday || now.DayOfWeek == DayOfWeek.Sunday) BackColor = Color.Green; else BackColor = Color.Red; } private UserPreferences () { } } } Приведенный код демонстрирует, как предпочтительный цвет сохраняется в статической переменной, которая инициализируется статическим конструктором. Это поле объявлено как доступное только для чтения, т.е. его значение может быть установлено только в конструкторе. Далее в этой главе вы узнаете подробнее о полях, доступных только для чтения. Код использует ряд удобных структур, которые поставляются Microsoft как часть библиотеки классов.NET - System.DateTime и System.Drawing.Color.DateTime. В Color.DateTime реализовано статическое свойство Now, возвращающее текущее время, и свойство экземпляра DayOfWeek, которое определяет, на какой день недели приходится дата и время. Структура Color применяется для хранения цветов. Здесь реализованы также различные статические свойства, наподобие Red и Green, которые, как показано в этом примере, возвращают часто используемые цвета. Чтобы использовать Color, во время компиляции необходимо сослаться на сборку System.Drawing.dll и добавить оператор using для пространства имен System.Drawing: using System; using System.Drawing; Статический конструктор можно протестировать с помощью следующего кода: class MainEntryPoint { static void Main(string[] args) { Console.WriteLine("Предпочтение пользователя: BackColor равно: " + UserPreferences.BackColor.ToString()); } } Компиляция и запуск этого кода даст следующий вывод: Предпочтение пользователя: BackColor равно: Color [Red] Конечно, если код выполняется в конце недели, предпочитаемым цветом может быть Green.
|
||||
Последнее изменение этой страницы: 2016-12-27; просмотров: 657; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.144.31.17 (0.011 с.) |