2

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

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

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

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

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

4 回答 4

3

结构始终具有无法覆盖的公共无参数构造函数:http: //msdn.microsoft.com/en-us/library/aa288208%28v=vs.71%29.aspx

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

var s = new IconEntry();
于 2012-05-16T08:59:04.600 回答
2

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

于 2012-05-16T08:59:17.157 回答
0

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

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

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

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

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

于 2012-12-05T23:16:55.640 回答
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 属性的完整分配。

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

于 2020-06-11T19:12:37.567 回答