为什么在属性声明中需要使用“field:”来表示“[field:NonSerialized]”?

19

我在 C# 关键字列表中找不到 "field"。 有人知道这方面的背景吗?


你能贴出更多的代码吗?你是在尝试创建一个新属性,还是在某个地方应用属性?更多的上下文会有所帮助。 - Nick
3
我忘记了那些。我已更新我的C#关键字清单以包含它们。谢谢!请参见http://blogs.msdn.com/ericlippert/archive/2009/05/11/reserved-and-contextual-keywords.aspx获取详细信息。 - Eric Lippert
5个回答

15

例如,如果您将事件标记为不可序列化,则这是必需的。它指定了属性适用的目标。

它是属性目标语法的一部分。来源于规范

attribute-target:
    field
    event
    method
    param
    property
    return
    type

参见NonSerializedAttribute的文档:

要将 NonSerializedAttribute 类应用于事件,请将属性位置设置为字段,如以下 C# 代码所示。

[field:NonSerializedAttribute()]

public event ChangedEventHandler Changed;


你不能序列化一个事件,而 NonSerializedAttribute 只适用于字段,所以我不明白 [field:NonSerializedAttribute()] 是什么意思,我也很惊讶它竟然编译通过了。 - Yuriy Faktorovich
2
重点是订阅事件的对象将被视为对象图的一部分,并在包含事件的对象序列化时进行序列化。要防止它们被序列化,您必须使用NonSerializedAttribute属性标记该事件。但是,由于NonSerializedAttribute仅适用于字段,因此您必须使用属性目标field标记它。 - jason
Yuriy,我认为委托被编译成类,因此在序列化时它们将与其调用列表一起序列化。在这种情况下,您需要将其设置为[NonSerialized],但它会引发编译错误,因此您需要指定field:NonSerialized。我认为他们在.NET 3.5中修复了这个问题。 - Stan R.
@Jason,我刚刚使用了XML序列化器,但事件没有被序列化。 - Yuriy Faktorovich
我可以看到EventHandler类被标记为Serializable,那么我如何为事件重现这种行为呢? - Yuriy Faktorovich
显示剩余2条评论

8

C#编译器通常不会有问题来确定属性应用于声明的哪个部分。我能想到三种情况可以使用它:

  1. 应用于程序集的属性。在AssemblyInfo.cs中非常明显。
  2. 应用于P/Invoke声明的返回值的属性,[return:MarshalAs]
  3. 将属性应用于没有访问器的属性或事件的备份变量。您的情况。

5

这是为了让您在字段上设置NonSerialized属性,这在序列化事件时非常有用。

例如,这将导致编译错误。

[NonSerialized]
public event SomeEventHandler SomeEvent;

为了解决这个问题,你需要使用field:
[field:NonSerialized]
public event SomeEventHandler SomeEvent;

关于这个问题的更多信息,请参见此处 -- 委托和序列化


但是你将其标记为NonSerialized,而事件无法序列化。 - Yuriy Faktorovich
Yuriy,我相信在.NET 3.0中,事件/委托被序列化为类,因此您必须将它们指定为NonSerialized。 - Stan R.
Yuriy,请查看以下链接http://msdn.microsoft.com/en-us/magazine/cc163902.aspx#S1 - Stan R.
1
你是正确的。我之前使用的 XmlSerializer 无法对类进行事件序列化,但 BinaryFormatter 可以。 - Yuriy Faktorovich

0

NonSerializedAttribute 只适用于字段,您可以按以下方式使用它:

[NonSerialized]
public string myString;

0

这个问题已经有答案了,但我会明确地演示自动实现属性的情况。

[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;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接