【问题标题】:Auto-Property Initializers not filled未填充自动属性初始化器
【发布时间】:2016-11-18 16:31:25
【问题描述】:

我有一个具有两个属性的类,一个填充了 c# 6.0 的新自动属性初始化程序,一个只实现了 getter 简写:

public SampleEnum SampleProp1 { get; } = SampleEnum.Value1;
public SampleEnum SampleProp2 { get { return SampleEnum.Value1; } }

此类是 wcf 端点的参数,当调用此端点时,SampleProp1 仅包含默认枚举值。

为什么会这样?

【问题讨论】:

    标签: c# .net


    【解决方案1】:

    C# 6.0 中的自动属性初始化器是语法糖,编译器将为初始化为给定表达式的属性创建一个支持字段。

    因此,您的代码等同于以下声明(我添加了一个类“SampleClass”以进行澄清):

    class SampleClass
    {
        // compiler-generated backing field initialized by the field initializer
        private readonly SampleEnum __sampleProp1 = SampleEnum.Value1;
    
        public SampleEnum SampleProp1 { get { return __sampleProp1; } }
    
        public SampleEnum SampleProp2 { get { return SampleEnum.Value1; } }
    }
    

    您的问题来自于 WCF 使用的反序列化器 does not execute the field initializers

    一种可能的解决方案是利用OnDeserializingOnDerserialized 属性并将所有初始化代码放入一个单独的方法中(如本问题所述:Field Initializer in C# Class not Run when Deserializing)。

    【讨论】:

      【解决方案2】:

      SampleEnum 真的是枚举吗?我在一个带有实际枚举的简单类中尝试了您的代码,它似乎工作正常。

      我可以看到SampleEnum实际上可能存在问题的地方实际上是一个类,并且在初始化具有属性的类时Value1尚未初始化。

      这是我尝试过的按预期工作的方法:

      class Program
      {
          static void Main(string[] args)
          {
              var x = new MyClass();
              Debug.Print("{0}", x.SampleProp1);
              Debug.Print("{0}", x.SampleProp2);
          }
          public class MyClass
          {
              public enum SampleEnum { Value0, Value1 , Value2 };
              public SampleEnum SampleProp1 { get; } = SampleEnum.Value1;
              public SampleEnum SampleProp2 { get { return SampleEnum.Value1; } }
          }
      }
      

      【讨论】:

      • 问题来自没有执行字段初始化程序的反序列化程序。只需使用 new 创建类的实例即可。
      • 是的。刚刚看到你的答案和我的差不多,并赞成你的。我没有考虑过序列化。干得好。