为什么要在将结构体传递给函数之前初始化它?

本文关键字:函数 初始化 结构体 为什么 | 更新日期: 2023-09-27 17:53:50

考虑以下代码:

 MyStruct j;
 j.I = 3;
 Console.WriteLine(j.I);

现在看看这个方法:

  public static void StructMod(MyStruct ms)
  {
      ms.I += 100;
      Console.WriteLine(ms.I);
  }

当我们将MyStruct传递给方法时,应该在传递之前初始化它吗?例如:

MyStruct j = new MyStruct()

为什么要在将结构体传递给函数之前初始化它?

除非struct是值类型?

MSDN的第一行:

结构类型是一个值类型…

与单个变量一样,结构体必须在被完全初始化后才能使用。考虑:
struct Foo
{
    public int Bar;
    public int Pop;
}
class Program
{
    static void Main(string[] args) {
        Foo f;
        f.Bar = 3;
        test(f);        // ERROR: Use of unassigned local variable 'f'
    }
    static void test(Foo f) {
        Console.WriteLine("{0}", f.Bar);
    }
}

这里的解决方案是初始化.Bar,或者简单地调用Foo构造函数f = new Foo(),它将所有成员初始化为默认值。

这与在struct s中添加参数化构造函数时得到的"Field ... must be fully assigned before control is returned to the caller"错误背后的逻辑相同。

经过一些测试,似乎无论您声明它的方式如何,它都被初始化了。

调用new ...的一个原因是执行构造函数中的代码(如果有的话)。

从MSDN中获取这个示例,例如:

public struct CoOrds
{
    public int x, y;
    public CoOrds(int p1, int p2)
    {
        x = p1;
        y = p2;
    }
}

你可以这样做,并使用c,但xy将是0

CoOrds c;

或者,您可以这样做,然后xy以值开始。

CoOrds c = new CoOrds(5,3);

(如果actor做了一些更有趣的事情,这将更有用)

如果您希望结构体具有特定的值,则将其初始化为该值。

如果您希望将结构体初始化为其默认值,则不需要显式初始化它。但是,如果结构体的默认值不明显,为了可读性起见,最好还是这样做。

作为旁注:可变结构真的很糟糕;您在示例中提出的整个场景是一种代码气味。参见为什么可变结构是"邪恶的"?

使用不可变结构体可以更安全地实现相同的行为,如

struct MyStruct 
{
  public readonly int I;
  public MyStruct(int i_initial)
  {
    I = i_initial;
  }
}
MyStruct j = new MyStruct(3);
public static void StructMod(MyStruct ms)
{
  Console.WriteLine(ms.I + 100);
}

特别要注意,从调用者的角度来看,这个函数的行为将与问题中的行为完全相同,因为结构体是按值传递的,与int等原语的传递方式相同。如果StructMod中的"Mod"在那里是因为您希望该函数修改值,那么这是一个很好的具体示例,说明为什么通常将可变类型作为对象而不是结构体更好。