В чём разница между полем, свойством и атрибутом
Не уверен правильно ли понимаю:
Поле – член класса, который определяет пассивную деятельность всех его экземпляров.
Свойство – это познанное нами поле — мы можем им манипулировать.
Признак Атрибут – то, по чему мы устанавливаем тип объекта.
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
Ответы с готовыми решениями:
Какая разница между автоматическим свойством и публичным полем?
Только начал изучать С# (после С++ кажется чуток не обычным) и прошу объяснить по-проще разницу.

Разница между составным атрибутом и многозначным В РМД
Как в таблицах отличаются составные атрибуты и многозначные? ФИО как я понимаю не будет в.

Разница между Методом, Свойством и Конструктором
Господа, наш путь тернист. На курсах заметил, что явно отстаю. Попросил задания у преподавателя.
208 / 164 / 29
Регистрация: 11.09.2013
Сообщений: 445
поле — объект, принадлежащий классу. может быть приватным или публичным (хотя последнее возбраняется). если в списке автодополнения VS2010 напротив чего-либо находится синий кубик, то это — поле
свойство — то, что предоставляет доступ к информационным ресурсам класса. чаще всего это обертка над полем, позволяющая работать с ним в рамках концепции ООП. призвано улучшить читаемость кода, его надежность и расширяемость. если в списке автодополнения VS2010 напротив чего-либо находится белая дощечка с надписями и рукой, то это — свойство
атрибут можно трактовать двояко. в общем случае это сущность, наделяющая что-либо какими-то дополнительными свойствами. в частном случае (применительно к C#) атрибут — штука, которая помогает управлять компилятором, сборками (да практически чем угодно, если уметь ими пользоваться). атрибутами можно снабжать классы, структуры, методы, поля, свойства, события. но это большая отдельная тема — лучше прочтите о ней отдельную статью
Регистрация: 23.04.2010
Сообщений: 93
Сообщение от sezada 
атрибут — штука, которая помогает управлять компилятором, сборками
И как это атрибут управляет компилятором и сборками?
208 / 164 / 29
Регистрация: 11.09.2013
Сообщений: 445
Сообщение от Smekalisty 
И как это атрибут управляет компилятором и сборками?
например, StructLayout управляет размещением полей в структурах. другие атрибуты добавляют метаданные, использующиеся при исполнении проекта. третьи вообще позволяют компилить тот или иной метод в зависимости от определенных констант
надеюсь, Ваш вопрос только прозвучал агрессивно, и ничего неприятного не имелось в виду
В чем отличие свойств и полей
Кроме обычных методов в языке C# предусмотрены специальные методы доступа, которые называют свойства . Они обеспечивают простой доступ к полям классов и структур, узнать их значение или выполнить их установку.
Определение свойств
Стандартное описание свойства имеет следующий синтаксис:
[модификаторы] тип_свойства название_свойства < get < действия, выполняемые при получении значения свойства>set < действия, выполняемые при установке значения свойства>>
Вначале определения свойства могут идти различные модификаторы, в частности, модификаторы доступа. Затем указывается тип свойства, после которого идет название свойства. Полное определение свойства содержит два блока: get и set .
В блоке get выполняются действия по получению значения свойства. В этом блоке с помощью оператора return возвращаем некоторое значение.
В блоке set устанавливается значение свойства. В этом блоке с помощью параметра value мы можем получить значение, которое передано свойству.
Блоки get и set еще называются акссесорами или методами доступа (к значению свойства), а также геттером и сеттером.
Person person = new Person(); // Устанавливаем свойство - срабатывает блок Set // значение "Tom" и есть передаваемое в свойство value person.Name = "Tom"; // Получаем значение свойства и присваиваем его переменной - срабатывает блок Get string personName = person.Name; Console.WriteLine(personName); // Tom class Person < private string name = "Undefined"; public string Name < get < return name; // возвращаем значение свойства >set < name = value; // устанавливаем новое значение свойства >> >
Здесь в классе Person определено приватное поле name , которая хранит имя пользователя, и есть общедоступное свойство Name . Хотя они имеют практически одинаковое название за исключением регистра, но это не более чем стиль, названия у них могут быть произвольные и не обязательно должны совпадать.
Через это свойство мы можем управлять доступом к переменной name . В свойстве в блоке get возвращаем значение поля:
А в блоке set устанавливаем значение переменной name. Параметр value представляет передаваемое значение, которое передается переменной name.
В программе мы можем обращаться к этому свойству, как к обычному полю. Если мы ему присваиваем какое-нибудь значение, то срабатывает блок set , а передаваемое значение передается в параметр value :
person.Name = "Tom";
Если мы получаем значение свойства, то срабатывает блок get , который по сути возвращает значение переменной name:
string personName = person.Name;
То есть по сути свойство Name ничего не хранит, оно выступает в роли посредника между внешним кодом и переменной name.
Возможно, может возникнуть вопрос, зачем нужны свойства, если мы можем в данной ситуации обходиться обычными полями класса? Но свойства позволяют вложить дополнительную логику, которая может быть необходима при установке или получении значения. Например, нам надо установить проверку по возрасту:
Person person = new Person(); Console.WriteLine(person.Age); // 1 // изменяем значение свойства person.Age = 37; Console.WriteLine(person.Age); // 37 // пробуем передать недопустимое значение person.Age = -23; // Возраст должен быть в диапазоне от 1 до 120 Console.WriteLine(person.Age); // 37 - возраст не изменился class Person < int age = 1; public int Age < set < if (value < 1 || value >120) Console.WriteLine("Возраст должен быть в диапазоне от 1 до 120"); else age = value; > get < return age; >> >
В данном случае переменная age хранит возраст пользователя. Напрямую мы не можем обратиться к этой переменной — только через свойство Age. Причем в блоке set мы устанавливаем значение, если оно соответствует некоторому разумному диапазону. Поэтому при передаче свойству Age значения, которое не входит в этот диапазон, значение переменной не будет изменяться:
person.Age = -23;Консольный вывод программы:
1 37 Возраст должен быть в диапазоне от 1 до 120 37
Таким образом, свойство позволяет опосредовать и контролировать доступ к данным объекта.
Свойства только для чтения и записи
Блоки set и get не обязательно одновременно должны присутствовать в свойстве. Если свойство определяет только блок get , то такое свойство доступно только для чтения — мы можем получить его значение, но не установить.
И, наоборот, если свойство имеет только блок set , тогда это свойство доступно только для записи — можно только установить значение, но нельзя получить:
Person person = new Person(); // свойство для чтения - можно получить значение Console.WriteLine(person.Name); // Tom // но нельзя установить // person.Name = "Bob"; // ! Ошибка // свойство для записи - можно устновить значение person.Age = 37; // но нелзя получить // Console.WriteLine(person.Age); // ! Ошибка person.Print(); class Person < string name = "Tom"; int age = 1; // свойство только для записи public int Age < set < age = value; >> // свойство только для чтения public string Name < get < return name; >> public void Print()=> Console.WriteLine($"Name: Age: "); >
Здесь свойство Name доступно только для чтения, поскольку оно имеет только блок get :
public string Name < get < return name; >>
Мы можем получить его значение, но НЕ можем установить:
Console.WriteLine(person.Name); // получить можно person.Name = "Bob"; // ! Ошибка - установить нельзя
А свойство Age, наоборот, доступно только для записи, поскольку оно имеет только блок set :
public int Age < set < age = value; >>
Можно установить его значение, но нельзя получить:
person.Age = 37; // установить можно Console.WriteLine(person.Age); // ! Ошибка - получить значение нельзя
Вычисляемые свойства
Свойства необязательно связаны с определенной переменной. Они могут вычисляться на основе различных выражений
Person tom = new("Tom", "Smith"); Console.WriteLine(tom.Name); // Tom Smith class Person < string firstName; string lastName; public string Name < get < return $""; > > public Person(string firstName, string lastName) < this.firstName = firstName; this.lastName = lastName; >>
В данном случае класс Person имеет свойство Name, которое доступно только для чтения и которое возвращает общее значение на основе значений переменных firstName и lastName.
Модификаторы доступа
Мы можем применять модификаторы доступа не только ко всему свойству, но и к отдельным блокам get и set:
Person tom = new("Tom"); // Ошибка - set объявлен с модификатором private //tom.Name = "Bob"; Console.WriteLine(tom.Name); // Tom class Person < string name = ""; public string Name < get < return name; >private set < name = value; >> public Person(string name) => Name = name; >
Теперь закрытый блок set мы сможем использовать только в данном классе — в его методах, свойствах, конструкторе, но никак не в другом классе:
При использовании модификаторов в свойствах следует учитывать ряд ограничений:
- Модификатор для блока set или get можно установить, если свойство имеет оба блока (и set, и get)
- Только один блок set или get может иметь модификатор доступа, но не оба сразу
- Модификатор доступа блока set или get должен быть более ограничивающим, чем модификатор доступа свойства. Например, если свойство имеет модификатор public, то блок set/get может иметь только модификаторы protected internal, internal, protected, private protected и private
Автоматические свойства
Свойства управляют доступом к полям класса. Однако что, если у нас с десяток и более полей, то определять каждое поле и писать для него однотипное свойство было бы утомительно. Поэтому в .NET были добавлены автоматические свойства. Они имеют сокращенное объявление:
class Person < public string Name < get; set; >public int Age < get; set; >public Person(string name, int age) < Name = name; Age = age; >>
На самом деле тут также создаются поля для свойств, только их создает не программист в коде, а компилятор автоматически генерирует при компиляции.
В чем преимущество автосвойств, если по сути они просто обращаются к автоматически создаваемой переменной, почему бы напрямую не обратиться к переменной без автосвойств? Дело в том, что в любой момент времени при необходимости мы можем развернуть автосвойство в обычное свойство, добавить в него какую-то определенную логику.
Стоит учитывать, что нельзя создать автоматическое свойство только для записи, как в случае со стандартными свойствами.
Автосвойствам можно присвоить значения по умолчанию (инициализация автосвойств):
Person tom = new(); Console.WriteLine(tom.Name); // Tom Console.WriteLine(tom.Age); // 37 class Person < public string Name < get; set; >= "Tom"; public int Age < get; set; >= 37; >
И если мы не укажем для объекта Person значения свойств Name и Age, то будут действовать значения по умолчанию.
Автосвойства также могут иметь модификаторы доступа:
class Person < public string Name < private set; get;>public Person(string name) => Name = name; >
Мы можем убрать блок set и сделать автосвойство доступным только для чтения. В этом случае для хранения значения этого свойства для него неявно будет создаваться поле с модификатором readonly, поэтому следует учитывать, что подобные get-свойства можно установить либо из конструктора класса, как в примере выше, либо при инициализации свойства:
class Person < // через инициализацию свойства public string Name < get; >= "Tom"; // через конструктор public Person(string name) => Name = name; >
Блок init
Начиная с версии C# 9.0 сеттеры в свойствах могут определяться с помощью оператора init (от слова «инициализация» — это есть блок init призван инициализировать свойство). Для установки значений свойств с init можно использовать только инициализатор, либо конструктор, либо при объявлении указать для него значение. После инициализации значений подобных свойств их значения изменить нельзя — они доступны только для чтения. В этом плане init-свойства сближаются со свойствами для чтения. Разница состоит в том, что init-свойства мы также можем установить в инициализаторе (свойства для чтения установить в инициализаторе нельзя). Например:
Person person = new(); //person.Name = "Bob"; //! Ошибка - после инициализации изменить значение нельзя Console.WriteLine(person.Name); // Undefined public class Person < public string Name < get; init; >= "Undefined"; >
В данном случае класс Person для свойства Name вместо сеттера использует оператор init . В итоге на строке
Person person = new();
предполагается создание объекта с инициализацией всех его свойств. В данном случае свойство Name получит в качестве значения строку «Undefined». Однако поскольку инициализация свойства уже произошла, то на строке
person.Name = "Bob"; // Ошибка
мы получим ошибку.
Как можно установить подобное свойство? Выше продемонстрирован один из способов — установка значения при определении свойства. Второй способ — через конструктор:
Person person = new("Tom"); Console.WriteLine(person.Name); // Tom public class Person < public Person(string name) =>Name = name; public string Name < get; init; >>
Третий способ — через инициализатор:
Person person = new() < Name = "Bob">; Console.WriteLine(person.Name); // Bob public class Person < public string Name < get; init; >= ""; >
В принцпе есть еще четвертый способ — установка через другое свойство с модификатором init :
var person = new Person() < Name = "Sam" >; Console.WriteLine(person.Name); // Sam Console.WriteLine(person.Email); // Sam@gmail.com public class Person < string name = ""; public string Name < get < return name; >init < name = value; Email = $"@gmail.com"; > > public string Email < get; init; >= ""; >
В данном случае свойство Name управляет полем для чтения name . Благодаря этому перед установкой значения свойства мы можем произвести некоторую предобработку. Кроме того, в выражении init устанавливается другое init-свойство — Email, которое для установки значения использует значение свойства Name — из имени получаем значение для электронного адреса.
Причем если при объявлении свойства указано значение, то в конструкторе мы можем его изменить. Значение, установленное в конструкторе, можно изменить в инициализаторе. Однако дальше процесс инициализации заканчивается. И значение не может быть изменено.
Сокращенная запись свойств
Как и методы, мы можем сокращать определения свойств. Поскольку блоки get и set представляют специальные методы, то как и обычные методы, если они содержат одну инструкцию, то мы их можем сократить с помощью оператора => :
class Person < string name; public string Name < get =>name; set => name = value; > >
Также можно сокращать все свойство в целом:
class Person < string name; // эквивалентно public string Name < get < return name; >> public string Name => name; >
модификатор required
Модификатор required (добавлен в C# 11) указывает, что поле или свойства с этим модификатором обязательно должны быть инициализированы. Например, в следующем примере мы получим ошибку:
Person tom = new Person(); // ошибка - свойства Name и Age не инициализированы public class Person < public required string Name < get; set; >public required int Age < get; set; >>
Здесь свойства Name и Age отмечены как обязательные для инициализации с помощью модификатора required , поэтому необходимо использовать инициализатор для их инициализации:
Person tom = new Person < Name = "Tom", Age = 38 >; // ошибки нет
Причем не важно, устанавливаем эти свойства в конструкторе или инициализируем при определении, все равно надо использовать инициализатор для установки их значений. Например, в следующем примере мы получим ошибку:
Person bob = new Person("Bob"); // ошибка - свойства Name и Age все равно надо установить в инициализаторе public class Person < public Person(string name) < Name = name; >public required string Name < get; set; >public required int Age < get; set; >= 22; >
Свойства полей, псевдонимы и опции отображения таблицы
У каждого поля, или столбца, в таблице атрибутов есть свойства, описывающие его содержимое, и как должны отображаться его данные. Можно просматривать и в некоторых случаях редактировать свойства для каждого поля на закладке Поля (Fields) в диалоговых окнах Свойства слоя (Layer Properties) и Свойства таблицы (Table Properties) . Настройки на закладке Поля (Fields) используются для определения способа отображения атрибутов в ArcMap, в том числе в окне атрибутивной таблицы, в окне Идентифицировать (Identify) и при редактировании в окне Атрибуты (Attributes) .
Например, вы можете:
- Определить, какие поля должны отображаться в таблице (видимые поля).
- Задать псевдоним для имени поля для того, чтобы поле отображалось в таблице с понятным именем. Псевдонимы полезны, т.к. вы не можете изменять имена полей в данных после их создания.
- Установить форматирование для числовых полей (денежные значения) или задать количество отображаемых знаков после запятой. Отформатированные данные отображаются в окне Идентифицировать (Identify) , в окне Атрибуты (Attributes) , в легендах, таблице содержания, окнах таблиц и т.д.
- Определить отображаемое поле, которое используется в окне Идентифицировать (Identify) , в окне Атрибуты (Attributes) и других функциональных возможностях в ArcMap.
- Написать выражение, которое можно использовать для построения более сложного элемента строки, а не содержимого одного поля.
- Установить параметры отображения таблицы и работы со столбцами.
Некоторые свойства полей задаются в момент создания класса пространственных объектов или таблицы и их потом нельзя изменить (тип данных, точность и количество знаков).
Перемещение по списку полей на закладке Поля (Fields)
Настройки, выбранные на закладке Поля (Fields) , в том числе видимость, порядок и псевдонимы полей, используются в ArcMap во всех местах работы с атрибутами – в окне атрибутивной таблицы, в окне Идентифицировать (Identify) и при редактировании в окне Атрибуты (Attributes) . Эти настройки применяются также к соединенным полям, хотя редактировать их можно только когда они не присоединены, то есть, в исходных таблицах.
Левая часть закладки Поля (Fields) содержит список со всеми полями класса пространственных объектов или таблицы, в том числе все присоединенные поля. Можно отметить или убрать отметку с поля, чтобы оно было или не было видно в ArcMap. Можно переключить видимость всех полей, щелкнув Включить все поля или Выключить все поля , удерживая нажатой клавишу CTRL и щелкнув на окошке для отметок, либо нажав клавиши CTRL+SPACEBAR , если поле подсвечено в списке.
Порядок, в котором поля перечислены на закладке Поля (Fields) – это порядок отображения полей в ArcMap по умолчанию. Чтобы изменить их порядок, щелкните на поле в списке и перетащите его в нужное место, либо воспользуйтесь кнопками со стрелочками вверх и вниз для перемещения поля по списку. Можно выбрать несколько полей и изменять их порядок одновременно. Щелкая на стрелках, вы перемещаете все выбранные поля на одну позицию выше или ниже по списку. Чтобы переместить поле в самый верх или низ списка, щелкните стрелку раскрывающегося списка рядом с кнопками стрелок и воспользуйтесь командой Переместить наверх (Move To Top) или Переместить вниз (Move To Bottom) .
Чтобы отсортировать список по алфавиту, нажмите кнопку Опции таблицы (Table Options) и выберите порядок по возрастанию или по убыванию. Чтобы вернуться к тому порядку, какой был у исходных данных, нажмите кнопку Опции таблицы (Table Options) и воспользуйтесь командой Восстановить порядок полей (Reset Field Order) . С помощью меню Опции таблицы (Table Options) можно переключаться между отображением псевдонимов и имен полей.
Установка свойств полей
Когда вы щелкаете на поле в списке слева, свойства отдельных полей отображаются на правой части закладки (если у вас выбрано несколько полей, правая часть остается пустой). Можно изменить свойства, показываемые в разделе Внешний вид (Appearance) , но нельзя изменить свойства, перечисленные в разделе Детали поля (Field Details) . Если щелкнуть на строке справа, в нижней части правой панели появится строчка с описанием этого свойства.
Свойства отображения указывают, каким образом содержимое этого поля отображается в ArcMap. Псевдоним поля – это его альтернативное название, которое может быть более понятным для пользователя, чем настоящее. Если нужно отличить определенные поля – например, чтобы их было лучше видно при редактировании в окне Атрибуты (Attributes) – установите в свойстве Выделить (Highlight) значение Да . При этом изменятся цвет шрифта и фоновая тень, чтобы поля отличались от остальных. Также можно задать полю режим «только для чтения», что означает, что его можно видеть, но не редактировать, независимо от прав доступа к базе геоданных. Кроме того, если вы работаете с числовыми полями, то можно установить формат чисел, нажав кнопку многоточия в строке Числовой формат (Number Format) . У каждой категории – валюта, проценты и т.д. – свой набор доступных опций форматирования.
Все элементы в списке Детали поля (Field Details) являются системными свойствами ArcGIS, к которым относятся тип данных поля, имя, точность, длина, названия доменов кодированных значений или интервалов, а также допустимо ли отсутствие значения (null). Они будут варьироваться в зависимости от источника данных (база геоданных, шейп-файл и т.д.) и типа поля (текст, длинное целое число, дата и т.д.). Так как эти свойства видны, но не редактируются, они показаны серым, а не черным цветом.
Псевдонимы полей
Псевдоним является альтернативным именем собой более понятное описание содержимого поля. В отличие от настоящих имен, псевдонимы могут не соответствовать ограничениям базы данных и могут содержать до 255 знаков – включая пробелы, цифры и специальные символы. Задавая псевдонимы, вы можете называть поля более информативно по сравнению с настоящими именами.
Например, вы можете задать псевдоним «Дата действия» для поля, хранящегося в базе данных как «DEED_DATE».
Существует два типа псевдонимов полей: псевдонимы полей класса пространственных объектов (только в базах геоданных) и псевдонимы полей слоя. С псевдонимами полей класса объектов вы работаете в ArcCatalog в диалоговом окне Свойства класса пространственных объектов (Feature Class Properties). Когда класс объектов базы данных добавляется в ArcMap, его псевдонимы полей изначально используются для псевдонимов полей слоя. Однако, после этого связи между двумя типами псевдонимов нет. Свойства, заданные в ArcMap, временно отменяют настройки свойства источника данных, но при этом не переносятся в источник данных. Это означает, что если вы измените псевдоним поля слоя, это не изменит псевдоним поля класса пространственных объектов, и если вы измените псевдоним поля в базе геоданных, это не обновит псевдоним поля слоя ни для какого слоя, созданного на основе этого класса объектов.
Сохранить то, что установлено на закладке Поля (Fields) , можно только сохраняя документ карты или слой в файл .lyr.
Опции отображения таблицы
Когда вы открываете таблицу, вы можете настроить ее вид несколькими способами. Например, если вам не нравится шрифт таблицы, установленный по умолчанию, вы можете изменить его, а также установить другой размер шрифта. Вы можете производить изменения для всех таблиц или только для одной – каждая таблица может иметь собственные индивидуальные настройки.
При изучении содержимого таблицы вы можете менять размеры столбцов для того, чтобы лучше видеть значения в таблице. Также вы можете менять столбцы местами для более удобного сравнения значений в одном столбце со значениями в другом. Закрепление столбцов таблицы также может быть полезно при изучении содержимого таблицы. Закрепленные столбцы жестко фиксируются в таблице слева и отделяются от других столбцов толстой черной линией. При горизонтальной прокрутке таблицы все остальные столбцы передвигаются как обычно, а закрепленные столбцы остаются зафиксированными.
Некоторые параметры отображения таблицы, которые вы можете задать, включают:
- Изменение ширины видимых полей и их перестановка
- Закрепление поля для того, чтобы оно всегда было на виду при прокрутке таблицы
- Выбор показывать или нет значения или описания для полей с подтипами и доменами
- Изменение цвета или шрифта, используемых для отображения атрибутов в таблицах
- Установка высоты заголовков и ячеек
- Задание символа, который показывает, что поле проиндексировано (индексы могут улучшить скорость обработки запросов)
Установка высоты заголовков и ячеек
Вы можете изменять высоту заголовков столбцов (верхняя строка таблицы атрибутов с именами полей) и ячеек. Увеличивая высоты заголовков и ячеек, вы можете увеличить высоту строк.
Если при том значении высоты заголовка столбца или ячейки, которое вы задали, достаточно места для дополнительных линий, то имя поля внутри заголовка столбца или содержимое ячейки перенесется на следующую линию, если не поместится при текущей ширине столбца. Это может быть особенно полезно в тех случаях, когда в таблице есть поля с длинным именами или длинные текстовые поля, такие как поля с описаниями или комментариями. Увеличение высоты заголовков или ячеек таблицы облегчит работу с такими полями.

Высота по умолчанию заголовка равна 125 процентам размера шрифта. Высота ячейки по умолчанию заголовка равна 115 процентам размера шрифта. Если вы установите высоту ячейки меньше 115%, это может затруднить редактирование содержимого ячеек.

Обычно для высоты заголовков и ячеек следует оставить значения по умолчанию как 125% и 115% на закладке Таблицы в меню Настройка > диалоговое окно Опции ArcMap , чтобы для всех создаваемых новых таблиц использовались стандартные установки. Если же нужно, чтобы у какой-то определенной таблицы строки были выше, чтобы длинные текстовые поля переносились на следующие строки, как показано на рисунке выше, задайте нужную настройку в диалоговом окне Опции таблицы (Table Options) > Оформление (Appearance) . В этом случае заданная высота строки будет применена только к данной конкретной таблице.
Быстрая установка свойств и псевдонимов полей
При открытом окне таблицы вы можете щелкнуть правой кнопкой мыши на заголовке поля и выбрать из меню пункт Свойства (Properties), чтобы открыть диалоговое окно, в котором можно установить и просмотреть определенные свойства этого поля. В этом диалоговом окне вы можете задать псевдоним поля, сделать поле невидимым или видимым, изменить форматирование для числовых полей и просмотреть (не изменяя) другие свойства поля, такие как разрешено ли отсутствие значений (null) в поле, точность и длина поля.
Установка ширины столбцов
В окне таблицы поля отображаются в виде столбцов. Вы можете потянуть разделители между полями влево или вправо, чтобы изменить ширину поля, вплоть до того, что поле может быть полностью скрыто.
Вы также можете автоматически восстановить ширину столбцов, чтобы отменить внесенные изменения. Команда Восстановить ширину столбцов по умолчанию (Restore Default Column Widths) в меню Опции таблицы возвращает для столбцов все значения ширины по умолчанию. Кроме того, она открывает все поля, полностью скрытые путем уменьшения их ширины до нуля. Команда Восстановить ширину столбцов по умолчанию (Restore Default Column Widths) не сбрасывает порядок столбцов, так что если столбцы были переставлены в окне таблицы, после применения этой команды их порядок не изменится.
Если какое-то поле таблицы полностью скрыто, это будет показано более толстым разделителем на месте этого поля. Таким образом, всегда легко увидеть, что одно или несколько полей скрыты. Если несколько полей скрыто на одном месте, это будет показано еще более толстой линией разделителя.

Чтобы открыть скрытое поле, потяните линию разделителя вправо, или щелкните дважды на разделителе. Чтобы открыть все спрятанные поля в таблице, используйте команду Восстановить ширину столбцов по умолчанию (Restore Default Column Widths) в меню Опции таблицы . Полное сокрытие полей в окне таблицы может быть полезно, т.к. позволяет настроить нужный вид таблицы, включая вид таблицы для печати с помощью команды Печать в меню Опции таблицы , без полного выключения полей, при котором поля выключаются и во всех других местах.
Связанные разделы
- Основные принципы добавления и удаления полей
- Таблица типов данных полей ArcGIS
- Редактирование атрибутов
Свойства
Свойства являются привилегированными компонентами C#. Язык определяет синтаксис, который позволяет разработчикам писать код, отражающий цели их проекта.
Свойства ведут себя как поля при доступе к им. Однако в отличие от полей свойства реализуются с помощью методов доступа, которые определяют инструкции, выполняемые при обращении к свойству или при его назначении.
Синтаксис свойства
Синтаксис свойств является естественным расширением полей. Поле определяет место хранения:
public class Person < public string? FirstName; // Omitted for brevity. >
Определение свойства содержит объявления для методов доступа get и set , которые получают и устанавливают значение этого свойства:
public class Person < public string? FirstName < get; set; >// Omitted for brevity. >
Синтаксис, показанный выше, является синтаксисом автосвойств. Компилятор создает место хранения для поля, поддерживающего свойство. Компилятор также реализует тело методов доступа get и set .
Бывает, что свойство необходимо инициализировать со значением, отличным от значения по умолчанию для его типа. C# позволяет это сделать, указав значение после закрывающей фигурной скобки свойства. В этом случае в качестве начального значения для свойства FirstName можно задать пустую строку, а не null . Для этого используется следующий код:
public class Person < public string FirstName < get; set; >= string.Empty; // Omitted for brevity. >
Как вы увидите далее в этой статье, конкретная инициализация особенно полезна для свойств, предназначенных только для чтения.
Вы можете определить хранилище самостоятельно, как показано ниже:
public class Person < public string? FirstName < get < return _firstName; >set < _firstName = value; >> private string? _firstName; // Omitted for brevity. >
Если реализация свойства представляет собой одиночное выражение, в качестве метода получения или задания можно использовать элементы, воплощающие выражение.
public class Person < public string? FirstName < get =>_firstName; set => _firstName = value; > private string? _firstName; // Omitted for brevity. >
Такой упрощенный синтаксис будет применяться в этой статье везде, где это возможно.
В примере выше определяется свойство для чтения и записи. Обратите внимание на ключевое слово value в методе доступа set. Метод доступа set всегда имеет один параметр с именем value . Метод доступа get должен возвращать значение, которое можно преобразовать в свойство ( string в этом примере).
Это основные сведения о синтаксисе. Существует множество различных вариантов, поддерживающих различные идиомы дизайна. Рассмотрим их, а также соответствующие параметры синтаксиса.
Проверка
Приведенные выше примеры демонстрируют один из простейших вариантов определения свойств: свойство для чтения и записи без проверки. Путем написания нужного кода в методах доступа get и set можно реализовать много разных сценариев.
Можно написать код в методе доступа set , чтобы гарантировать, что значения, представленные свойством, всегда будут допустимыми. Например, предположим, что одно из правил для класса заключается в Person том, что имя не может быть пустым или пробелом. Это можно реализовать следующим образом:
public class Person < public string? FirstName < get =>_firstName; set < if (string.IsNullOrWhiteSpace(value)) throw new ArgumentException("First name must not be blank"); _firstName = value; >> private string? _firstName; // Omitted for brevity. >
Предыдущий пример можно упростить, воспользовавшись выражением throw в рамках проверки метода задания свойства:
public class Person < public string? FirstName < get =>_firstName; set => _firstName = (!string.IsNullOrWhiteSpace(value)) ? value : throw new ArgumentException("First name must not be blank"); > private string? _firstName; // Omitted for brevity. >
В приведенном выше примере код применяет правило о том, что имя не может быть пустым или содержать только пробелы. Если разработчик пишет
hero.FirstName = "";
Это назначение создает исключение ArgumentException . Поскольку метод доступа set свойства должен иметь тип возвращаемого значения void, чтобы сообщить об ошибках в методе доступа set, создается исключение.
Этот синтаксис можно расширить для любых компонентов в вашем сценарии. Можно проверить отношения между разными свойствами или соответствие любым внешним условиям. Любые допустимые операторы C# являются допустимыми в методе доступа свойства.
Управление доступом
До этого момента все примеры определения свойств определяли свойства для чтения и записи с помощью открытых методов доступа. Это не единственные операции доступа для свойств. Можно создать свойства, доступные только для чтения, или назначить другой уровень доступа для методов set и get. Предположим, ваш класс Person должен допускать изменение значения свойства FirstName только из других методов этого класса. Вы можете предоставить методу доступа set уровень доступа private , а не public :
public class Person < public string? FirstName < get; private set; >// Omitted for brevity. >
Теперь к свойству FirstName можно получать доступ из любого кода, но назначить его можно только из другого кода в классе Person .
Вы можете добавить любой ограничивающий модификатор доступа для методов доступа set или get. Модификатор доступа, установленный для отдельного метода доступа, должен задавать более строгие ограничения, чем модификатор доступа для определения свойства. Приведенный выше пример допустим, так как свойство FirstName является открытым ( public ) а метод доступа set — закрытым ( private ). Невозможно объявить private свойство с помощью public метода доступа. Свойство также можно объявить как protected , internal , protected internal или даже private .
Кроме того, можно установить более строгий модификатор доступа get . Например, свойство public может быть открытым, а метод доступа get ограничен типом private . Этот сценарий редко реализуется на практике.
Только для чтения
Вы также можете ограничить изменения свойством , чтобы его можно было задать только в конструкторе. Внести соответствующие изменения в класс Person можно следующим образом:
public class Person < public Person(string firstName) =>FirstName = firstName; public string FirstName < get; >// Omitted for brevity. >
Только инициализация
В предыдущем примере требуется, чтобы вызывающие элементы использовали конструктор, содержащий FirstName параметр . Вызывающие объекты не могут использовать инициализаторы объектов для назначения значения свойству . Для поддержки инициализаторов можно сделать set метод доступа методом init доступа, как показано в следующем коде:
public class Person < public Person() < >public Person(string firstName) => FirstName = firstName; public string? FirstName < get; init; >// Omitted for brevity. >
Предыдущий пример позволяет вызывающему объекту Person создать с помощью конструктора по умолчанию, даже если этот код не задает FirstName свойство . Начиная с C# 11, можно требовать, чтобы вызывающие объекты устанавливали это свойство:
public class Person < public Person() < >[SetsRequiredMembers] public Person(string firstName) => FirstName = firstName; public required string FirstName < get; init; >// Omitted for brevity. >
Приведенный выше код вносит два дополнения в Person класс . Во-первых FirstName , объявление свойства включает модификатор required . Это означает, что любой код, создающий новый Person объект, должен задать это свойство. Во-вторых, конструктор, принимаюющий firstName параметр, имеет System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute атрибут . Этот атрибут сообщает компилятору, что этот конструктор задает все required члены.
Не путайте required с не допускающей значения NULL. Допустимо задать свойству required null значение или default . Если тип не допускает значения NULL, как string в этих примерах, компилятор выдает предупреждение.
Вызывающие объекты должны использовать конструктор с SetsRequiredMembers или задавать FirstName свойство с помощью инициализатора объекта, как показано в следующем коде:
var person = new VersionNinePoint2.Person("John"); person = new VersionNinePoint2.Person< FirstName = "John">; // Error CS9035: Required member `Person.FirstName` must be set: //person = new VersionNinePoint2.Person();
Вычисляемые свойства
Свойству не нужно просто возвращать значение поля-члена. Можно создать свойства, возвращающие вычисляемое значение. Расширим объект Person так, чтобы он возвращал полное имя, вычисляемое путем объединения имени и фамилии:
public class Person < public string? FirstName < get; set; >public string? LastName < get; set; >public string FullName < get < return $""; > > >
В примере выше используется функция интерполяции строк для создания форматированной строки для полного имени.
Можно также использовать члены, воплощающие выражения, которые обеспечивают более краткий способ создания вычисляемого свойства FullName :
public class Person < public string? FirstName < get; set; >public string? LastName < get; set; >public string FullName => $" "; >
Члены, воплощающие выражения, используют синтаксис лямбда-выражений для определения метода, который содержит одно выражение. Здесь это выражение возвращает полное имя объекта person.
Свойства с вычислением в кэше
Вы можете сочетать концепцию вычисляемого свойства с хранением и созданием свойства с вычислением в кэше. Например, можно изменить свойство FullName таким образом, чтобы форматирование строки выполнялось только при первом доступе к нему.
public class Person < public string? FirstName < get; set; >public string? LastName < get; set; >private string? _fullName; public string FullName < get < if (_fullName is null) _fullName = $""; return _fullName; > > >
Обратите внимание, что приведенный выше код содержит ошибку. Если код изменяет значение свойств FirstName или LastName , ранее вычисленное поле fullName является недопустимым. Вам потребуется изменить методы доступа set свойств FirstName и LastName , чтобы вычислить поле fullName еще раз:
public class Person < private string? _firstName; public string? FirstName < get =>_firstName; set < _firstName = value; _fullName = null; >> private string? _lastName; public string? LastName < get =>_lastName; set < _lastName = value; _fullName = null; >> private string? _fullName; public string FullName < get < if (_fullName is null) _fullName = $""; return _fullName; > > >
Эта окончательная версия вычисляет свойство FullName только при необходимости. Если ранее вычисленная версия является допустимой, используется она. Если другое изменение состояния делает ранее вычисленную версию недействительной, она будет пересчитана. Разработчикам, используюющим этот класс, не нужно знать подробности реализации. Ни одно из этих внутренних изменений не влияет на использование объекта person. Это главная причина для использования свойств для предоставления доступа к членам данных объекта.
Присоединение атрибутов к автоматически реализуемым свойствам
Атрибуты поля можно присоединить к созданному компилятором резервному полю в автоматически реализуемых свойствах. Например, рассмотрим изменение класса Person , который добавляет уникальное целочисленное свойство Id . Вы записываете Id свойство с помощью автоматически реализуемого свойства, но проект не требует сохранения Id свойства. NonSerializedAttribute можно прикреплять только к полям, а не свойствам. Можно прикрепить NonSerializedAttribute к резервному полю для свойства Id с помощью описателя field: в атрибуте, как показано в следующем примере:
public class Person < public string? FirstName < get; set; >public string? LastName < get; set; >[field:NonSerialized] public int Id < get; set; >public string FullName => $" "; >
Этот способ подходит для любого атрибута, который вы прикрепляете к резервному полю в автоматически реализуемом свойстве.
Реализация INotifyPropertyChanged
Последним сценарием, где необходимо написать код в методе доступа к свойству, является поддержка интерфейса INotifyPropertyChanged, используемого для уведомления клиентов привязки данных об изменении значения. При изменении значения свойства объект вызывает событие INotifyPropertyChanged.PropertyChanged, указывающее на изменение. Библиотеки привязки данных, в свою очередь, изменяют отображаемые элементы на основе этого изменения. В следующем примере кода показано, как можно реализовать свойства INotifyPropertyChanged для FirstName этого класса person.
public class Person : INotifyPropertyChanged < public string? FirstName < get =>_firstName; set < if (string.IsNullOrWhiteSpace(value)) throw new ArgumentException("First name must not be blank"); if (value != _firstName) < _firstName = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(FirstName))); >> > private string? _firstName; public event PropertyChangedEventHandler? PropertyChanged; >
Оператор ?. называется оператором объединения со значением NULL. Он проверяет наличие пустой ссылки перед вычислением правой стороны оператора. В конечном итоге, если нет подписчиков на событие PropertyChanged , код для вызова события не выполняется. В этом случае без такой проверки будет создано исключение NullReferenceException . Для получения дополнительной информации см. events . В этом примере также используется новый оператор nameof для преобразования символа имени свойства в текстовое представление. Использование nameof позволяет сократить количество ошибок, когда вы неправильно ввели имя свойства.
Реализация INotifyPropertyChanged — это пример случая, когда можно писать код в методах доступа для поддержки необходимых сценариев.
Подведем итоги
Свойства — это своего рода интеллектуальные поля в классе или объекте. Из-за пределов объекта они представляются полями в объекте. Однако для реализации свойства можно использовать полную палитру функциональных возможностей C#. Вы можете предоставлять разные уровни доступа, выполнять проверки, отложенное вычисление или любые другие требования, необходимые в вашем сценарии.
Совместная работа с нами на GitHub
Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.
The .NET documentation is open source. Provide feedback here.
Обратная связь
Отправить и просмотреть отзыв по
