结构构造函数和布局

时间:2015-06-17 16:57:27

标签: c#

[根据答案和评论进行编辑和扩展]

我们有一个 public C#API,它使用没有任何构造函数的嵌套结构。 注意: public 表示它不是我们的,我们需要通过固定的序列化函数与它进行通信。

因此

public struct Inner {
    public int f1;
    public int f2;
    public Inner(int _f1, int _f2)
    {
      this.f1 = _f1;
      this.f2 = _f2;
    }
};

public struct Outer {
    public int z;
    public Inner f;
    public Outer (int _f1, int _f2, int _z)
    {
      this.f = new Inner(_f1, _f2);
      this.z = _z;
    }
};

public class HelloWorld
{
    static public void Main ()
    {
       Outer someVar = new Outer(4,5,6);

给定的类型没有InnerOuter构造函数。

我建议我们添加构造函数(如上所述),因为初始化变得相当繁琐。实际的结构比显示的大得多,导致数十个

someVar.f.f1 = initialzier

然而,我团队的一些成员认为我们不允许更改API'

这有官方的立场吗? 这里通过官方我不是指人类约定/最佳实践,而是指C#语义;即可以在C#struct中添加构造函数来更改struct布局吗?

同样相关的问题是内部结构上的new或构造函数初始化一个临时位置,然后将其复制到外部结构中,还是将它原位初始化到外部结构中?

上面的代码中有2个new。根据@supercat的回答,存储分配可能会也可能不会被优化掉。有没有办法保证?

[基本上我缺少C指针指向内部的能力 struct并将其传递给初始化函数]

另请注意,{/ 1}}应该/不应该使用,因此不讨论。因此,它可能用于历史可能与C等互操作 我们的代码需要与之互操作的另一方的原因。

2 个答案:

答案 0 :(得分:1)

结构构造函数在语义上等同于修改this的结构成员函数,除了C#编译器将转向:

someVar = new someStructType(this, that, theOther);

进入:

var temp = default(someStructType);
temp..ctor(this, that, theOther);
someVar = temp;

someVar..ctor(this, that, theOther);

和 - 在后一种情况下 - 编译器不会坚持在调用someVar方法之前必须初始化.ctor(这样会破坏构造函数的点)。

后者效率更高,但编译器只会在认为时使用它,后者将等同于前者。请注意,有一些场景,特别是涉及混合语言代码,其中C#行为将显着影响程序语义,但在大多数情况下行为是可观察的,编译器将使用前者。

从语法的角度来看,构造函数调用看起来最像是一个返回结构类型的函数。但是,这样的函数通常需要在临时中构建一个新结构,然后让调用者将它复制到所需的位置,这与构造函数有时不同,后者有时可以直接写入新变量。

答案 1 :(得分:0)

  

[基本上我缺少C能够将指针指向内部结构并将其传递给初始化函数]

据我所知,你可以在C#中做同样的事情:

public struct Inner {
    public static void Init(out Inner value,int _f1,int _f2) {
        value.f1=_f1;
        value.f2=_f2;
    }
    public int f1;
    public int f2;
}

public struct Outer {
    public static void Init(out Outer value,int _f1,int _f2,int _z) {
        Inner.Init(out value.f,_f1,_f2);
        value.z=_z;
    }
    public int z;
    public Inner f;
}

public class HelloWorld {
    static public void Main() {
        Outer someVar;
        Outer.Init(out someVar,4,5,6);