Зачем мне нужно "field:" в объявлении моего атрибута "[field:NonSerialized]"?

Я не могу найти "поле", указанное в качестве ключевого слова C#. Кто-нибудь знает предысторию этого?

5 ответов

Решение

Компилятор C# обычно без труда выясняет, к какой части объявления относится атрибут. Я могу вспомнить три случая, когда вы могли бы использовать его:

  1. Атрибуты, которые применяются к сборке. Очень хорошо видно в AssemblyInfo.cs
  2. Атрибут, примененный к возвращаемому значению объявления P/Invoke, [return:MarshalAs]
  3. Наличие атрибута применяется к резервной переменной свойства или события без средств доступа. Твой случай.

Это необходимо, например, если вы помечаете событие как не сериализуемое. Он указывает цель, к которой применяется атрибут.

Это часть целевого синтаксиса атрибута. Из спецификации:

attribute-target:
    field
    event
    method
    param
    property
    return
    type

Смотрите также документацию для NonSerializedAttribute:

Чтобы применить NonSerializedAttribute класс в событие, установите местоположение атрибута в поле, как показано в следующем коде C#.

[field:NonSerializedAttribute()]

public event ChangedEventHandler Changed;

Это позволяет вам устанавливать атрибут NonSerialized для полей, это полезно при сериализации событий.

Например, это даст вам ошибку компиляции

[NonSerialized]
public event SomeEventHandler SomeEvent;

Чтобы исправить это, вы должны использовать field:

[field:NonSerialized]
public event SomeEventHandler SomeEvent;

Подробнее об этом здесь - делегаты и сериализация

NonSerializedAttribute применим только к полям, вы можете использовать его следующим образом:

[NonSerialized]
public string myString;

На этот вопрос уже был дан ответ, но я подробно продемонстрирую случай автоматически реализуемых свойств.

[NonSerialized] применяется только к полям, поскольку он относится к средству двоичного форматирования, которое сериализует данные полей, в отличие от чего-то вроде Json.NET, который сериализует свойства.

      [NonSerialized]
public int Value;

Мы не можем использовать его непосредственно для автоматически реализуемых свойств — следующее не компилируется:

      [NonSerialized]             
public int Value { get; set; }

Мы можем использовать модификатор «field:», чтобы применить атрибут к автоматически реализуемому резервному полю:

      [field: NonSerialized]
public int Value { get; set; }

Что эквивалентно:

      public int Value 
{ 
    get => backingField;
    set => backingField = value;
}

[NonSerialized]
private int backingField;
Другие вопросы по тегам