【问题标题】:Do auto-implemented properties support attributes?自动实现的属性是否支持属性?
【发布时间】:2009-01-21 11:21:21
【问题描述】:

有人告诉我,在 c# 中,自动实现的属性上不允许使用属性。真的吗?如果是,为什么?

编辑:我从一本流行的 LINQ 书籍中获得了这些信息,简直不敢相信! 编辑:请参阅 Paul Kimmel 的 LINQ Unleashed 的第 34 页,他说“自动实现的属性不允许使用属性,所以如果你需要属性,请自行选择

【问题讨论】:

  • 您能准确地说信息是什么吗? (顺便说一句,我认为给出这本书的名称和参考文献是公平的。)
  • 习惯于相信它——在文本和工具中。我们都会犯错。我记得那天 Turbo C++ 1.0 编译器在复制构造函数(或与之相关的东西)上有内部内存泄漏。在我证明之前,我不敢相信这是编译器的错,而不是源代码的错误。他们在下一个版本中修复了它。

标签: c# attributes automatic-properties


【解决方案1】:

您可以毫无问题地将属性应用于自动属性。

引用MSDN:

属性是允许的 自动实现的属性,但 显然不在支持领域 因为那些无法从 你的源代码。如果您必须使用 a 的支持字段上的属性 属性,只需创建一个常规 属性。

【讨论】:

    【解决方案2】:

    证明这是错误的最简单方法就是测试它:

    using System;
    using System.ComponentModel;
    using System.Reflection;
    
    class Test
    {
        [Description("Auto-implemented property")]
        public static string Foo { get; set; }  
    
        static void Main(string[] args)
        {
            var property = typeof(Test).GetProperty("Foo");
            var attributes = property.GetCustomAttributes
                    (typeof(DescriptionAttribute), false);
    
            foreach (DescriptionAttribute description in attributes)
            {
                Console.WriteLine(description.Description);
            }
        }
    }
    

    我建议您向作者发送电子邮件,以便他可以将其发布为勘误表。如果他的意思是你不能将属性应用到字段,这会给他一个更仔细解释的机会。

    【讨论】:

      【解决方案3】:

      我认为作者的意思是,您不能将自定义属性应用于私有支持字段。 例如,如果要将自动属性标记为非序列化,则不能这样做:

      [Serializable]
      public class MyClass
      {
          [field:NonSerializedAttribute()]
          public int Id
          {
              get;
              private set;
          }
      }
      

      此代码可以编译,但不起作用。 您可以将属性应用于属性本身,但您不能将其应用于支持字段。

      【讨论】:

      • 这不是最好的。我们甚至已经有了field: 指令!
      • 无法获得评论:) 我们确实有一个 field; 指令,但该指令不会对具有支持字段的属性执行任何操作。
      • 抱歉!我的意思是我希望您示例中的语法有效:)
      【解决方案4】:

      另请注意,任何 Automatic 属性也将应用 CompilerGeneratedAttribute。

      【讨论】:

        【解决方案5】:

        当前版本的 Visual Studio 和 C# 编译器支持此功能。我使用启用了 C# 8.0 的 VS 16.4.2 进行了测试。我不确切知道它是在哪个版本中启用的,但这是个好消息。

        语法:

        [field: NonSerialized]
        public SomeNonSerializableType MyAutoProperty { get; set; } = DefaultValueAfterSerialization;
        

        实际用例;支持整洁/可往返的合格 XML 序列化,没有杂乱的支持字段,但避免运行时异常并解决代码分析错误 CA2235:

        /// <summary>
        /// XML name table for serialization.
        /// </summary
        [XmlSerializerNamespaces]
        [field: NonSerialized]
        public XmlSerializerNamespaces XmlNamespaces { get; set; } = new XmlSerializerNamespaces();
        

        如果您正在使用 .NET Core 3、.NET Standard 2.1 或更高版本开发新的“SDK”样式项目之一,它将立即工作,因为它们默认为语言版本 8。否则对于所有“旧版”.NET框架和非 SDK 项目,您必须将“LangVersion”设置添加到您的项目 as documented here 到“8.0”或“最新”。

        【讨论】:

          猜你喜欢
          • 2015-03-28
          • 1970-01-01
          • 2012-02-07
          • 2019-04-03
          • 1970-01-01
          • 1970-01-01
          • 2016-11-13
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多