简体   繁体   English

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

[英]Struct with auto-implemented properties and constructor initializer

Recently a compiler warning and (very useful) hint prompted me to write the code below.最近编译器警告和(非常有用的)提示提示我编写下面的代码。

I had no idea you could do this, but it is perfectly legal, and also convenient in that I can declare a managed struct with public properties similar to public fields of an unmanaged struct, and also initialize it with an object instead of having to pass all the fields as parameters.我不知道你可以这样做,但它是完全合法的,而且也很方便,因为我可以声明一个具有类似于非托管结构的公共字段的公共属性的托管结构,并且还可以使用对象对其进行初始化,而不必通过所有字段作为参数。

What confuses me is that this appears to call the explicit parameterless constructor, which would of course be illegal for this struct.让我感到困惑的是,这似乎调用了显式无参数构造函数,这对于这个结构来说当然是非法的。

What's going on here, and has this syntax always been supported?这里发生了什么,是否一直支持这种语法?

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

A struct always has a public parameterless constructor which can't be overriden: http://msdn.microsoft.com/en-us/library/aa288208%28v=vs.71%29.aspx结构总是有一个不能被覆盖的公共无参数构造函数: http : //msdn.microsoft.com/en-us/library/aa288208%28v=vs.71%29.aspx

This means that a user still would be able to create an instance of this struct that is not initialized according to your logic but with default values for all properties:这意味着用户仍然可以创建此结构的实例,该实例未根据您的逻辑进行初始化,但具有所有属性的默认值:

var s = new IconEntry();

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

Is there any reason you're exposing properties rather than fields for your struct?您是否有任何理由为结构公开属性而不是字段? If the semantics of your data type imply that如果您的数据类型的语义暗示

  1. The entire state of an instance will be fully defined by the values exposed by some public members, such that two instances for whom all those report or contain identical values will be considered identical.一个实例的整个状态将完全由一些公共成员公开的值定义,这样所有这些报告或包含相同值的两个实例将被认为是相同的。
  2. Instances of the struct with any combination of values for the aforementioned members may be created easily, given the desired values in question.给定所讨论的所需值,可以轻松创建具有上述成员的任何值组合的结构实例。

that sounds like a perfect fit for a PODS (Plain Old Data Struct).这听起来非常适合 PODS(Plain Old Data Struct)。 Exposed fields are more efficient and less quirky than struct properties.公开的字段比结构属性更有效,也更不古怪。 Given that all struct types always expose all fields for mutation or capture by struct assignment, the encapsulation offered by struct properties is of extremely limited value.鉴于所有结构类型总是暴露所有字段以通过结构赋值进行变异或捕获,结构属性提供的封装价值极其有限。

The way you have your constructor written, your struct will have all fields set to all-bits-zero, and then be passed repeatedly to methods which will update one field at a time with the desired value.按照您编写构造函数的方式,您的结构会将所有字段设置为所有位为零,然后重复传递给方法,这些方法将一次更新一个字段并使用所需值。 The fact that the struct is specified as initialized to all-bits-zero by the this will make the compiler happy, but using many individual properties to set up fields piecemeal is inefficient.结构被指定为初始化为所有位为零的this将使编译器满意,但使用许多单独的属性来设置字段是低效的。

Incidentally, even better than a constructor in many cases would be a static method which simply takes your struct as a ref parameter.顺便说一句,在许多情况下甚至比构造函数更好的是静态方法,它只是将您的结构作为ref参数。 In many cases, using a constructor with a struct will result in an unnecessary copy operation which could be avoided by using a static method with a ref parameter.在许多情况下,使用带有结构的构造函数会导致不必要的复制操作,这可以通过使用带有ref参数的静态方法来避免。

Since structs are value types, it's data members should be initialized if you are explicitly invoke the constructor.由于结构是值类型,如果您显式调用构造函数,则应初始化它的数据成员。 And mention "this()" to intimate compiler to complete the assignment of auto implemented properties if anything you mentioned.并提及“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);
    }
}

Main method:主要方法:

class Program
     {
         static void Main()
         {
             Student st = new Student("John")
             {
                 ID=101
             };

             st.PrintDetails(); 

         } 
     }

Output:
ID : 101 Name: John

If you are not mention "this()", compiler forcefully ask you to complete the full assignment of ID property.如果你没有提到“this()”,编译器会强行要求你完成ID属性的全部赋值。

If you are not explicitly invoke the constructor, compiler implicitly set default values for the struct data members.如果没有显式调用构造函数,编译器会为结构体数据成员隐式设置默认值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM