Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Примечание.
Эта статья является спецификацией компонентов. Спецификация служит проектным документом для функции. Этот документ включает предлагаемые изменения спецификации, а также информацию, необходимую во время проектирования и разработки функции. Эти статьи публикуются до тех пор, пока предложенные изменения спецификации не будут завершены и включены в текущую спецификацию ECMA.
Может возникнуть некоторое несоответствие между спецификацией компонентов и завершенной реализацией. Эти различия отражены в соответствующих заметках с заседания по дизайну языка (LDM) .
Дополнительные сведения о процессе внедрения спецификаций функций в стандарт языка C# см. в статье о спецификациях .
Вопрос чемпиона: https://github.com/dotnet/csharplang/issues/9058
Сводка
Разрешить модификатору partial
событий и конструкторов разделять части объявления и реализации, аналогичные частичным методам и частичным свойствам и индексаторам.
partial class C
{
partial C(int x, string y);
partial event Action<int, string> MyEvent;
}
partial class C
{
partial C(int x, string y) { }
partial event Action<int, string> MyEvent
{
add { }
remove { }
}
}
Мотивация
C# уже поддерживает частичные методы, свойства и индексаторы. Частичные события и конструкторы отсутствуют.
Частичные события будут полезны для слабых библиотек событий , где пользователь может писать определения:
partial class C
{
[WeakEvent]
partial event Action<int, string> MyEvent;
void M()
{
RaiseMyEvent(0, "a");
}
}
Генератор исходного кода, предоставляемый библиотекой, обеспечивает реализации.
partial class C
{
private readonly WeakEvent _myEvent;
partial event Action<int, string> MyEvent
{
add { _myEvent.Add(value); }
remove { _myEvent.Remove(value); }
}
protected void RaiseMyEvent(int x, string y)
{
_myEvent.Invoke(x, y);
}
}
Частичные события и частичные конструкторы также могут быть полезны для создания кода взаимодействия, например в Xamarin , где пользователь может писать частичные конструкторы и определения событий:
partial class AVAudioCompressedBuffer : AVAudioBuffer
{
[Export("initWithFormat:packetCapacity:")]
public partial AVAudioCompressedBuffer(AVAudioFormat format, uint packetCapacity);
[Export("create:")]
public partial event EventHandler Created;
}
И генератор источника создаст привязки (к Objective-C в этом случае):
partial class AVAudioCompressedBuffer : AVAudioBuffer
{
[BindingImpl(BindingImplOptions.GeneratedCode | BindingImplOptions.Optimizable)]
public partial AVAudioCompressedBuffer(AVAudioFormat format, uint packetCapacity) : base(NSObjectFlag.Empty)
{
// Call Objective-C runtime:
InitializeHandle(
global::ObjCRuntime.NativeHandle_objc_msgSendSuper_NativeHandle_UInt32(
this.SuperHandle,
Selector.GetHandle("initWithFormat:packetCapacity:"),
format.GetNonNullHandle(nameof(format)),
packetCapacity),
"initWithFormat:packetCapacity:");
}
public partial event EventHandler Created
{
add { /* ... */ }
remove { /* ... */ }
}
}
Подробный дизайн
Общая информация
Синтаксис объявления событий (§15.8.1) расширен, чтобы разрешить partial
модификатор:
event_declaration
- : attributes? event_modifier* 'event' type variable_declarators ';'
+ : attributes? event_modifier* 'partial'? 'event' type variable_declarators ';'
- | attributes? event_modifier* 'event' type member_name
+ | attributes? event_modifier* 'partial'? 'event' type member_name
'{' event_accessor_declarations '}'
;
Синтаксис объявления конструктора экземпляра (§15.11.1) расширен для разрешения partial
модификатора:
constructor_declaration
- : attributes? constructor_modifier* constructor_declarator constructor_body
+ : attributes? constructor_modifier* 'partial'? constructor_declarator constructor_body
;
Обратите внимание, что существует предложение разрешить partial
модификатор в любом месте между модификаторами, а не только в качестве последнего (также для объявлений методов, свойств и типов).
Объявление события с partial
модификатором считается частичным объявлением событий и связано с одним или несколькими частичными событиями с указанными именами (обратите внимание, что одно объявление события без доступа может определять несколько событий).
Объявление конструктора с partial
модификатором считается частичным объявлением конструктора и связано с частичным конструктором с указанной сигнатурой .
Частичное объявление события, как говорят, является объявлениемреализации, когда оно указывает event_accessor_declarations
или имеет extern
модификатор.
В противном случае это определяющее объявление.
Частичное объявление конструктора называется определяющим объявлением, когда оно имеет тело с точкой с запятой и не имеет модификатора. В противном случае это объявление , реализующее.
partial class C
{
// defining declarations
partial C();
partial C(int x);
partial event Action E, F;
// implementing declarations
partial C() { }
partial C(int x) { }
partial event Action E { add { } remove { } }
partial event Action F { add { } remove { } }
}
Только определяющее объявление частичного члена участвует в поиске и учитывается в местах использования и для создания метаданных. (За исключением комментариев документации, как описано ниже.) Сигнатура реализации объявления используется для анализа связанных тел на наличие null-значений.
Частичное событие или конструктор:
- Может быть объявлен только как член частичного типа.
- Должна быть одна определяющая и одна реализующая декларация.
- Наличие модификатора
abstract
не разрешено. - Не удается явно реализовать член интерфейса.
Частичное событие не соответствует полю (§15.8.2), т. е.
- У него нет резервных хранилищ или методов доступа, созданных компилятором.
- Его можно использовать только в операциях
+=
и-=
, а не в качестве значения.
Определение частичного объявления конструктора не может иметь инициализатор конструктора (: this()
или : base()
; §15.11.2).
Анализ перерыва
Разрешение partial
модификатора в дополнительных контекстах является критическим изменением:
class C
{
partial F() => new partial(); // previously a method, now a constructor
@partial F() => new partial(); // workaround to keep it a method
}
class partial { }
Чтобы упростить средство синтаксического анализа языка, модификатор partial
принимается в любом объявлении метода (например, в локальных функциях и методах скриптов верхнего уровня), даже если мы явно не указываем изменения грамматики выше.
Атрибуты
Атрибуты результирующего события или конструктора — это объединенные атрибуты частичных объявлений в соответствующих позициях. Объединенные атрибуты объединяются в неопределенном порядке и дубликаты не удаляются.
method
attribute_target (§22.3) игнорируется в частичных объявлениях событий.
Атрибуты аксессора используются только из объявлений аксессора, которые могут присутствовать только в контексте объявления реализации.
Обратите внимание, что param
и return
attribute_targetуже игнорируются во всех объявлениях событий.
Атрибуты Caller-info в реализующей декларации игнорируются компилятором, как указано в предложении о частичных свойствах в разделе Caller-info attributes (обратите внимание, что это применимо ко всем частичным элементам , включая частичные события и конструкторы).
Подписи
Оба объявления частичного элемента должны иметь соответствующие подписи , аналогичные частичным свойствам:
- Различия типов и ссылок между частичными объявлениями, которые являются значительными для среды выполнения, приводят к ошибке во время компиляции.
- Различия в именах элементов кортежа между частичными объявлениями приводят к ошибке во время компиляции.
- Объявления должны иметь одинаковые модификаторы, хотя модификаторы могут отображаться в другом порядке.
- Исключение: это не относится к модификатору
extern
, который может отображаться только в объявлении реализации.
- Исключение: это не относится к модификатору
- Все остальные синтактические различия в подписях частичных объявлений приводят к предупреждению во время компиляции со следующими исключениями:
- Списки атрибутов не должны совпадать, как описано выше.
- Различия в NULL-контексте (например, без аннотаций или с аннотациями) не вызывают предупреждений.
- Значения параметров по умолчанию не должны совпадать, но предупреждение сообщается, когда объявление реализации конструктора имеет значения параметров по умолчанию (так как они будут игнорироваться, так как только определяющее объявление участвует в поиске).
- Предупреждение возникает, когда имена параметров отличаются между объявлениями конструктора при его определении и реализации.
- Различия в нулевой доступности, не связанные с неявной нулевой доступностью, приводят к предупреждениям.
Комментарии к документации
Можно включать комментарии документации как в определение, так и в реализацию декларации. Обратите внимание, что комментарии в документации не поддерживаются в аксессорах событий.
Когда примечания к документу присутствуют только в одном из объявлений частичного члена, эти примечания используются как обычно (отображаются через API Roslyn, выдаются в XML-файл документации).
Когда комментарии документа присутствуют в обоих объявлениях частичного члена, все комментарии документа об определении объявления удаляются, и используются только комментарии документации по реализации объявления.
Если имена параметров отличаются между объявлениями частичного элемента, paramref
элементы используют имена параметров из объявления, связанного с комментарием документации в исходном коде.
Например, комментарий paramref
в документации, размещенный на объявлении реализации, ссылается на символы параметров этого объявления, используя их имена.
Это может быть запутанным, так как сигнатура метаданных будет использовать имена параметров из определяющего объявления.
Рекомендуется убедиться, что имена параметров соответствуют объявлениям частичного члена, чтобы избежать этой путаницы.
Открытые вопросы
Виды участников
Хотим ли мы частичных событий, конструкторов, операторов, полей? Мы предлагаем первые два типа элементов, но можно рассмотреть любое другое подмножество.
Частичные первичные конструкторы также могут рассматриваться, например, разрешая пользователю иметь один и тот же список параметров в нескольких объявлениях частичного типа.
Расположения атрибутов
Следует ли распознавать спецификатор цели атрибута [method:]
для частичных событий (или только определяющих деклараций)?
Затем результирующие атрибуты доступа будут представлять собой объединение method
-целевых атрибутов из обеих частей объявления (или только из определяющих), а также атрибутов самонацеливания и method
-целевой направленности из методов доступа реализующего объявления.
Объединение атрибутов из разных категорий объявлений было бы беспрецедентным, и действительно, текущая реализация сопоставления атрибутов в Roslyn этого не поддерживает.
Мы также можем рассмотреть вопрос о распознавании [param:]
и [return:]
не только на частичных событиях, но и всех событий, которые являются похожими на поля и внешние события.
Дополнительные сведения см. в статье https://github.com/dotnet/roslyn/issues/77254.
C# feature specifications