具有自动实现的属性和构造函数初始值设定项的Struct

时间:2012-05-16 08:55:35

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

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

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

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

这里发生了什么,并且一直支持这种语法吗?

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();
    }
}

4 个答案:

答案 0 :(得分:3)

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

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

var s = new IconEntry();

答案 1 :(得分:2)

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

答案 2 :(得分:0)

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

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

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

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

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

答案 3 :(得分:0)

由于结构是值类型,因此如果您显式调用构造函数,则应初始化其数据成员。并提及“ 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属性的完整分配。

如果未显式调用构造函数,则编译器将隐式设置struct数据成员的默认值。