Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Заметка
Эта статья является спецификацией компонентов. Спецификация служит проектным документом для функции. Он включает предлагаемые изменения спецификации, а также информацию, необходимую во время проектирования и разработки функции. Эти статьи публикуются до тех пор, пока предложенные изменения спецификации не будут завершены и включены в текущую спецификацию ECMA.
Может возникнуть некоторое несоответствие между спецификацией компонентов и завершенной реализацией. Эти различия отражены в соответствующих заметках с заседания по дизайну языка (LDM) .
Дополнительные сведения о процессе внедрения спецификаций функций в стандарт языка C# см. в статье о спецификациях .
Проблема чемпиона: https://github.com/dotnet/csharplang/issues/6420
Грамматика
property_declarationграмматики (§14.7.1) обновляется следующим образом:
property_declaration
- : attributes? property_modifier* type member_name property_body
+ : attributes? property_modifier* 'partial'? type member_name property_body
;
Примечания. Это несколько похоже на то, как method_header(§15.6.1) и class_declaration(§15.2.1) специфицированы. (Обратите внимание, что вопрос #946 предлагает смягчить требование упорядочивания и, вероятно, будет применяться ко всем объявлениям, которые допускают модификатор partial
. Мы намерены определить такое смягчение требования в ближайшем будущем и реализовать его в том же выпуске, в котором эта функция будет внедрена.)
Определение и реализация объявлений
Когда объявление свойства включает частичный модификатор , это свойство называется частичным свойством. Частичные свойства могут быть объявлены только как члены частичных типов.
частичное свойство называется определяющим объявлением, когда все его методы доступа содержат только точки с запятой, и оно не содержит модификатора extern
. В противном случае это объявление , реализующее.
partial class C
{
// Defining declaration
public partial string Prop { get; set; }
// Implementing declaration
public partial string Prop { get => field; set => field = value; }
}
Так как мы зарезервировали синтаксическую форму с точками с запятой для определяющих объявлений, частичное свойство не может быть автоматически реализовано. Поэтому мы настраиваем автоматически применяемые свойства (§15.7.4) следующим образом:
Автоматически реализованное свойство (или автоматическое свойство для краткости) — это не абстрактное, не внешнее, не частичное, не имеющее ссылочного типа свойство с аксессорами, состоящими только из точки с запятой.
примечания. Это полезно для компилятора — посмотреть на одно объявление в изоляции и понять, является ли оно объявляющим или реализующим объявлением. Поэтому мы не хотим разрешать автоматические свойства, включая два идентичных объявления свойств partial
, например. Мы не считаем, что варианты использования этой функции включают реализацию частичного свойства с автоматическим свойством, но в случаях, когда требуется тривиальная реализация, мы считаем, что ключевое слово field
делает вещи достаточно простыми.
Частичное свойство должно иметь одно объявление , которое определяет, и одно объявление , которое реализует.
примечания. Мы также не считаем, что полезно разрешить разделение объявления на более чем двух частях, чтобы разрешить реализации различных методов доступа в разных местах, например. Поэтому мы просто имитируем схему, созданную частичными методами.
Только определяющее объявление частичного свойства участвует в поиске, подобно тому, как только объявление частичного метода участвует в разрешении перегрузки.
Примечания. В компиляторе мы предполагаем, что в списке элементов отображается только символ объявляющей декларации, а доступ к символу реализующей части можно получить через символ, связанный с определением. Однако некоторые функции, такие как анализ, допускающий значение NULL, могут просматривать в объявление реализации, чтобы обеспечить более полезное поведение.
partial class C
{
public partial string Prop { get; set; }
public partial string Prop { get => field; set => field = value; }
public C() // warning CS8618: Non-nullable property 'Prop' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
{
}
}
Частичное свойство не разрешено иметь модификатор abstract
.
Частичное свойство не может явно реализовать свойства интерфейса.
Объединение атрибутов
Как и частичные методы, атрибуты в результирующем свойстве являются объединенными атрибутами частей, объединенными в неопределенном порядке, и дубликаты не удаляются.
Атрибуты информации о вызывающем
Мы корректируем следующую формулировку из стандарта :
Ошибка заключается в наличии одинакового атрибута caller-info на параметре как в определении, так и в реализации части частичного метода
в декларации элемента. Применяются только атрибуты caller-info в определяющей части, тогда как атрибуты caller-info, присутствующие только в реализующей части, игнорируются.
- Описанная ошибка не соответствует определениям этих атрибутов из-за отсутствия
AllowMultiple = true
. Многократное использование, в том числе в различных частичных объявлениях, приводит к ошибке. - Когда атрибуты caller-info применяются к параметру в части реализации частичного метода, компилятор Roslyn сообщает предупреждение. Он также сообщает предупреждение для того же сценария в частичном свойстве.
Сопоставление подписей
Собрание LDM на 14 сентября 2020 г. установило набор "строгих" требований для сопоставления подписей частичных методов, которые были введены в предупреждающей волне. Частичные свойства имеют требования, аналогичные требованиям частичных методов для максимально возможного соответствия подписей, за исключением того, что все диагностические уведомления о несоответствиях сообщаются по умолчанию и не скрыты за волной предупреждений.
Требования к совпадению подписей:
- Различия типов и видов ссылок между объявлениями частичных свойств, имеющие значительное влияние на результат выполнения, приводят к ошибке во время компиляции.
- Различия в именах элементов кортежа в объявлениях частичных свойств приводят к ошибке во время компиляции, аналогичной частичным методам.
- Объявления свойств и их объявления доступа должны иметь одинаковые модификаторы, хотя модификаторы могут отображаться в другом порядке.
- Исключение: это не относится к модификатору
extern
, который может отображаться только в реализации объявления.
- Исключение: это не относится к модификатору
- Все остальные синтактические различия в сигнатурах объявлений частичных свойств приводят к предупреждению во время компиляции со следующими исключениями:
- Списки атрибутов в частичных объявлениях свойства не обязаны совпадать. Вместо этого выполняется слияние атрибутов на соответствующих позициях согласно разделу Слияние атрибутов.
- Различия контекста, допускающие значение NULL, не вызывают предупреждений. Другими словами, разница, в которой один из типов является nullable-oblivious, и другой тип либо nullable-annotated, либо не-nullable-annotated не приводит к каким-либо предупреждениям.
- Значения параметров по умолчанию не должны соответствовать. Предупреждение сообщается, когда часть реализации частичного индексатора имеет значения параметров по умолчанию. Это похоже на существующее предупреждение, которое возникает, когда часть реализации частичного метода имеет значения параметров по умолчанию.
- Предупреждение возникает, когда имена параметров отличаются в определяющем и реализующем объявлениях. Имена параметров из части определения используются в местах применения и при генерации.
- Различия в нулевой доступности, не связанные с неявной нулевой доступностью, приводят к предупреждениям. При анализе тела акцессора используется сигнатура части реализации. Подпись части определения используется при анализе сайтов использования и отправке. Это согласуется с частичными методами.
partial class C1
{
public partial string Prop { get; private set; }
// Error: accessor modifier mismatch in 'set' accessor of 'Prop'
public partial string Prop { get => field; set => field = value; }
}
partial class C2
{
public partial string Prop { get; init; }
// Error: implementation of 'Prop' must have an 'init' accessor to match definition
public partial string Prop { get => field; set => field = value; }
}
partial class C3
{
public partial string Prop { get; }
// Error: implementation of 'Prop' cannot have a 'set' accessor because the definition does not have a 'set' accessor.
public partial string Prop { get => field; set => field = value; }
}
partial class C4
{
public partial string this[string s = "a"] { get; set; }
public partial string this[string s] { get => s; set { } } // ok
public partial string this[int i, string s = "a"] { get; set; }
public partial string this[int i, string s = "a"] { get => s; set { } } // CS1066: The default value specified for parameter 's' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments
}
Комментарии к документации
Мы хотим, чтобы поведение документированных комментариев к частичным свойствам соответствовало тому, что мы выпустили для частичных методов. Это поведение подробно описано в https://github.com/dotnet/csharplang/issues/5193.
Допускается включить комментарии документации по определению или реализации части частичного свойства. (Обратите внимание, что примечания к документам не поддерживаются при доступе к свойствам.)
Если примечания документа присутствуют только в одной из частей свойства, эти комментарии документов обычно используются (отображаются через ISymbol.GetDocumentationCommentXml()
, записываются в XML-файл документации и т. д.).
Когда комментарии к документу присутствуют в обоих частях, все комментарии документации по части определения удаляются, а используются только комментарии к документации по части реализации.
Например, следующая программа:
/// <summary>
/// My type
/// </summary>
partial class C
{
/// <summary>Definition part comment</summary>
/// <returns>Return value comment</returns>
public partial int Prop { get; set; }
/// <summary>Implementation part comment</summary>
public partial int Prop { get => 1; set { } }
}
Приводит к следующему XML-файлу документации:
<?xml version="1.0"?>
<doc>
<assembly>
<name>ConsoleApp1</name>
</assembly>
<members>
<member name="T:C">
<summary>
My type
</summary>
</member>
<member name="P:C.Prop">
<summary>
Implementation part comment
</summary>
</member>
</members>
</doc>
Если имена параметров отличаются между частичными объявлениями, <paramref>
элементы используют имена параметров из того объявления, которое связано с комментарием документации в исходном коде. Например, paramref для комментария документа, размещенного в объявлении реализации, относится к символам параметра в объявлении реализации с использованием их имен параметров. Это согласуется с частичными подходами.
/// <summary>
/// My type
/// </summary>
partial class C
{
public partial int this[int x] { get; set; }
/// <summary>
/// <paramref name="x"/> // warning CS1734: XML comment on 'C.this[int]' has a paramref tag for 'x', but there is no parameter by that name
/// <paramref name="y"/> // ok. 'Go To Definition' will go to 'int y'.
/// </summary>
public partial int this[int y] { get => 1; set { } } // warning CS9256: Partial property declarations 'int C.this[int x]' and 'int C.this[int y]' have signature differences.
}
Приводит к следующему XML-файлу документации:
<?xml version="1.0"?>
<doc>
<assembly>
<name>ConsoleApp1</name>
</assembly>
<members>
<member name="T:C">
<summary>
My type
</summary>
</member>
<member name="P:C.Item(System.Int32)">
<summary>
<paramref name="x"/> // warning CS1734: XML comment on 'C.this[int]' has a paramref tag for 'x', but there is no parameter by that name
<paramref name="y"/> // ok. 'Go To Definition' will go to 'int y'.
</summary>
</member>
</members>
</doc>
Это может быть запутано, так как сигнатура метаданных будет использовать имена параметров из части определения. Рекомендуется убедиться, что имена параметров совпадают между частями, чтобы избежать этой путаницы.
Индексаторы
На собрании LDM 2 ноября 2022 г.этот функционал будет доступен индексаторам.
Грамматика индексаторов изменяется следующим образом:
indexer_declaration
- : attributes? indexer_modifier* indexer_declarator indexer_body
+ : attributes? indexer_modifier* 'partial'? indexer_declarator indexer_body
- | attributes? indexer_modifier* ref_kind indexer_declarator ref_indexer_body
+ | attributes? indexer_modifier* 'partial'? ref_kind indexer_declarator ref_indexer_body
;
Параметры частичного индексатора должны совпадать во всех объявлениях в соответствии с теми же правилами, что и сигнатуры соответствия . Объединение атрибутов выполняется по частичным параметрам индексатора.
partial class C
{
public partial int this[int x] { get; set; }
public partial int this[int x]
{
get => this._store[x];
set => this._store[x] = value;
}
}
// attribute merging
partial class C
{
public partial int this[[Attr1] int x]
{
[Attr2] get;
set;
}
public partial int this[[Attr3] int x]
{
get => this._store[x];
[Attr4] set => this._store[x] = value;
}
// results in a merged member emitted to metadata:
public int this[[Attr1, Attr3] int x]
{
[Attr2] get => this._store[x];
[Attr4] set => this._store[x] = value;
}
}
Открытые проблемы
Другие типы участников
Член сообщества открыл обсуждение, чтобы получить поддержку для частичных событий. На заседании LDM 2 ноября 2022 годамы решили отложить поддержку мероприятий, отчасти потому, что никто в то время не просил её. Мы можем вернуться к этому вопросу, так как этот запрос в настоящее время пришел, и это было более года с тех пор, как мы в последний раз обсуждали его.
Мы могли бы и дальше зайти ещё дальше, разрешая частичные объявления конструкторов, операторов, полей и т. д., но неясно, оправдано ли проектное бремя для них только потому, что мы уже создаём частичные свойства.
C# feature specifications