C#Struct通过构造函数分配值

时间:2013-01-12 19:59:26

标签: c# constructor struct

作为我的代码的一部分,我创建了以下结构:

struct ItemInformation
{
    public int ItemNumber;
    public double HighPrice, LowPrice, MedianPrice;

    public ItemInformation(int number, double highP, double lowP) : this()
    {
        this.ItemNumber = number;
        this.HighPrice = highP;
        this.LowPrice = lowP;
        this.MedianPrice = CalculateMedian(highP, lowP);
    }

    private double CalculateMedian(double high, double low)
    {
        return 0.5 * (high + low);
    }
}

我知道结构包含四个数据但我希望只能指定三个作为第四个,MedianPrice,完全由高价和低价决定。所以我想用

ItemInformation jacket;

以及

ItemInformation jacket = new ItemInformation(1234, 145.70, 73.20)

创建结构的实例,但我似乎无法让它工作。除MedianPrice外,结构中的所有项都已正确设置。这可能是一个可变性问题,但我并没有真正改变这里的价值观。我只是根据其他两个设置一个值,我想只使用三个输入创建结构的实例。有没有人对我如何做到这一点有任何建议?任何建议将不胜感激。谢谢。

4 个答案:

答案 0 :(得分:3)

.net中的结构通常应符合两种风格中的一种,我称之为“透明”和“#34;和"不透明"。请注意,MSDN指南似乎是由一个认为一切都像一个类对象行为的人编写的,并且失败的行为就像一个类对象是一个缺陷;因此,他们忽略了这样一个事实:透明结构本身可以有有用的语义,而且在很多情况下,使不透明结构效率低下的因素可能会使类更低效。

透明结构是暴露所有字段的结构,结构的状态只不过是其字段中值的组合。透明结构可能具有只读和方便属性"根据其字段的值计算(例如,带有字段DX,DY和DZ的透明Vector3d结构可能具有基于这些字段计算的Length属性)但应该清楚这些属性不构成结构状态的一部分,而是用于对字段执行计算的便捷简写。例如,vec.Length可以替代SomeLibrary.Distance3d(vec.DX, vec.DY, vec.DZ)

透明结构类型的变量为每个字段分配一个变量;如果需要,每个字段可以作为其自己的单独变量来访问。通过值传递透明结构类型与单独传递其所有字段大致相同(在某些情况下,它可能更有效;在其他情况下,更少)。通过ref传递透明结构类型与传递对象引用具有相同的固定成本,无论字段数量如何。

如果现有版本满足以下所有条件,并且所有可能的未来版本都会满足结构,那么结构在很多情况下应该是透明的[意味着不符合标准的结构将不被视为兼容替代品]

  1. 有一些固定的可读成员(字段或属性)可以暴露其整个状态
  2. 给定这些成员的任何期望值集合,可以创建具有这些值的实例(不禁止任何值组合)。
  3. 结构的默认值应该是将所有成员设置为各自类型的默认值。

如果结构符合上述条件,公开公开其字段将不允许外部代码执行任何其他方式无法执行的操作,除非它可能允许以较快的速度执行的操作,并且可能允许线程-safe操作,否则需要使用原子基元安全地执行锁定。

当然,并非所有结构都符合上述标准,但如果符合标准的那些结构变得透明,那么性能通常可以得到改善 - 有时甚至是相当大的。实际上,结构的大部分原因通常被认为只是略微快于类,因为它们的性能因不必要地使它们变得不透明而受阻。

不透明结构是指其状态在语义上表示其字段中的值以外的其他结构的结构。例如,大小为1234且指数为2的Decimal可能代表数字量12.34。除了通过为整个事物计算新值之外,不可能仅改变不透明结构的一个方面。不透明的结构可能试图在其字段上强制执行不变量,但重要的是要注意,由于结构分配的工作方式,在许多情况下,对于滥用线程的代码(但不具有任何线程)是可能的。特殊执行权限)滥用线程以生成违反结构的结构实例。不变式。

当应用于不透明结构时,Microsoft的指南非常好。这种结构通常应避免暴露财产安置者。 PointRectangle等类型不代表偏离该规则。 相反,它们代表了首先不应该是不透明结构的类型 - 它们应该是透明结构。在某些情况下,暴露属性设置器的不透明结构可以提供通过任何其他方式无法实现的语义,但是这样的结构有一些烦人的缺陷,这通常使得它们不像实现相同目的的其他方法那样令人满意。

关于你提出的结构,我建议要么使它成为一个有三个字段的透明结构,并且MedianPrice是一个属性,每次调用它时计算这三个字段的中位数,或者是一个带有四个字段的不透明结构,它可以在其构造函数中计算MedianPrice。我的决定将基于读取MedianPrice的相对频率,与代码想要修改其中一个价格而不修改其他价格的相对频率相比较。如果前者更常见,不透明的结构。如果是后者,透明结构。请注意,如果使用透明结构开始编写代码以利用它,则可能难以调整代码来处理不透明的结构。相比之下,使用不透明结构编写的代码也可以使用透明结构,但效率不如原来的那么高。

请注意,透明结构与其他类型之间的效率差异随结构大小而增长。例如,假设需要存储许多3d三角形的坐标。可以定义一个透明结构Triangle3d,其中包含三个类型为Point3d的字段(每个字段将包含三个数字X,Y,Z),并将所有三角形存储在Triangle3d[]中。给定这样的定义,可以容易地修改任何三角形中的单个点的单个坐标,而不必触摸或甚至不读取任何其他三角形。相反,如果使用不透明结构或不可变类类型,则更改甚至单个属性将需要将旧实例中的所有信息复制到新实例。类型具有的字段越多,使用不透明或不可变类型的成本就越高。如果一个人使用了一个可变的类类型,那么修改就会很便宜,但是一个方法没有很好的方法来保持上述数组使三角形的坐标可用于调用者而不暴露底层存储对象,除了手工 - 将所有字段值复制到新的不可变对象。 因此,与Microsoft的指导方针相反,对于许多使用模式,类型具有的字段越多,其作为透明结构而不是类的优势就越大。

顺便提一下,有些人会认为外露字段结构违反了封装。我认为相反。像KeyValuePair<TKey,TValue>这样的类型应该包含TKey类型的字段,以及类型TValue的另一个类型。由于可以自由地读取这两个字段,因此可以为它们分配对其各自类型有效的任何值的组合,并且实际上没有任何有用的类型的未来版本可能可以做到的透明结构不能同样做,即所谓的&#34;封装&#34;除了增加零值之外什么都不做,只会降低代码的效率。

答案 1 :(得分:2)

您应该通过创建所有实例字段readonly来使结构不可变。此外,MedianPrice可以是属性,并且它不需要struct值中的数据:

struct ItemInformation
{
  public readonly int ItemNumber;
  public readonly double HighPrice, LowPrice;  // no MedianPrice here

  public ItemInformation(int number, double highP, double lowP) // no need to chain this()
  {
    this.ItemNumber = number;
    this.HighPrice = highP;
    this.LowPrice = lowP;
  }

  public double MedianPrice
  {
    get
    {
      return 0.5 * (HighPrice + LowPrice);
    }
  }
}

答案 2 :(得分:0)

我认为问题可能是,你所指的是:

this.Median

而不是

this.MedianPrice

答案 3 :(得分:0)

起初

ItemInformation jacket;

并不意味着创建了jacket变量。你无法使用它。

试试这个:

public ItemInformation(int number = 0, double highP = 0, double lowP = 0)
{
    ItemNumber = number;
    HighPrice = highP;
    LowPrice = lowP;
    MedianPrice = 0;
    MedianPrice = CalculateMedian(highP, lowP);
}

用法:

ItemInformation jacket1 = new ItemInformation();
ItemInformation jacket2 = new ItemInformation(1234, 145.70, 73.20);