【问题标题】:Struct with auto-implemented properties and constructor initializer具有自动实现属性和构造函数初始化程序的结构
【发布时间】:2023-04-02 01:09:02
【问题描述】:

最近一个编译器警告和(非常有用的)提示提示我编写下面的代码。

我不知道你可以这样做,但这是完全合法的,而且也很方便,因为我可以声明一个具有类似于非托管结构的公共字段的公共属性的托管结构,并且还可以用一个对象而不是必须将所有字段作为参数传递。

让我困惑的是,这似乎调用了显式的无参数构造函数,这对于这个结构当然是非法的。

这是怎么回事,这种语法是否一直受到支持?

internal struct IconEntry
{
    public byte Width { get; set; }
    public byte Height { get; set; }
    public byte ColorCount { get; set; }
    public byte Reserved { get; set; }
    public short Planes { get; set; }
    public short BitCount { get; set; }
    public int BytesInRes { get; set; }
    public int ImageOffset { get; set; }

    public IconEntry(BinaryReader reader)
        : this()
    {
        Width = reader.ReadByte();
        Height = reader.ReadByte();
        ColorCount = reader.ReadByte();
        Reserved = reader.ReadByte();
        Planes = reader.ReadInt16();
        BitCount = reader.ReadInt16();
        BytesInRes = reader.ReadInt32();
        ImageOffset = reader.ReadInt32();
    }
}

【问题讨论】:

标签: c# .net constructor struct automatic-properties


【解决方案1】:

结构总是有一个不能被覆盖的公共无参数构造函数:http://msdn.microsoft.com/en-us/library/aa288208%28v=vs.71%29.aspx

这意味着用户仍然可以创建此结构的实例,该实例未根据您的逻辑进行初始化,但所有属性都具有默认值:

var s = new IconEntry();

【讨论】:

  • +1 或者确实让它完全未初始化但仍具有默认值。
  • 啊...好吧,这很有道理。奇怪... VS2010 的编译器警告中使用的术语与 MSDN 中使用的术语不一致。它提示我添加一个“构造函数初始化程序”,就像在我的示例代码中一样,但是在 struct 构造函数的 msdn 部分的任何地方都找不到这样做 - 这就是让我来到这里的原因。
【解决方案2】:

所有结构都有一个无参数的构造函数——它只是隐式的(例如,它总是存在于一个默认例程中——一个将所有值设置为 0 的例程)——你不能有一个显式的构造函数(例如,你在代码中定义的一个)。

【讨论】:

    【解决方案3】:

    您是否有任何理由公开结构的属性而不是字段?如果您的数据类型的语义暗示

    1. 实例的整个状态将完全由某些公共成员公开的值定义,因此所有这些报告或包含相同值的两个实例将被视为相同。
    2. 在给定所需值的情况下,可以轻松创建具有上述成员值的任意组合的结构实例。

    这听起来非常适合 PODS(普通旧数据结构)。与结构属性相比,暴露的字段更有效且不那么古怪。鉴于所有结构类型总是暴露所有字段以通过结构赋值进行突变或捕获,因此结构属性提供的封装价值极其有限。

    按照您编写构造函数的方式,您的结构将所有字段设置为所有位为零,然后重复传递给方法,这些方法将使用所需的值一次更新一个字段。结构被this 指定为初始化为全零的事实将使编译器满意,但是使用许多单独的属性来设置字段是低效的。

    顺便说一句,在许多情况下,甚至比构造函数更好的是静态方法,它只是将您的结构作为ref 参数。在许多情况下,使用带有结构的构造函数会导致不必要的复制操作,这可以通过使用带有ref 参数的静态方法来避免。

    【讨论】:

      【解决方案4】:

      由于结构是值类型,如果你显式调用构造函数,它的数据成员应该被初始化。如果您提到任何内容,请向亲密的编译器提及“this()”以完成自动实现属性的分配。

      struct Student
      {        
          string _sname;       
      
          public int ID
          {
              get; set;
          }
      
          internal Student(string sname):this()
          {            
              _sname = sname;
          }
      
          internal void PrintDetails()
          {
              Console.WriteLine("ID : {0} Name: {1}", ID, _sname);
          }
      }
      

      主要方法:

      class Program
           {
               static void Main()
               {
                   Student st = new Student("John")
                   {
                       ID=101
                   };
      
                   st.PrintDetails(); 
      
               } 
           }
      
      Output:
      ID : 101 Name: John
      

      如果你没有提到“this()”,编译器会强制要求你完成ID属性的完整赋值。

      如果没有显式调用构造函数,编译器会为结构数据成员隐式设置默认值。

      【讨论】:

        猜你喜欢
        • 2018-10-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-13
        相关资源
        最近更新 更多