64

在回答这个帖子时踢了一些小结构,我意外地遇到了以下情况:

以下结构,使用 int 字段是完全合法的:

struct MyStruct
{ 
    public MyStruct ( int size ) 
    { 
        this.Size = size; // <-- Legal assignment.
    } 

    public int Size; 
}

但是,使用自动属性的以下结构无法编译:

struct MyStruct
{ 
    public MyStruct ( int size ) 
    { 
        this.Size = size; // <-- Compile-Time Error!
    } 

    public int Size{get; set;}
}

返回的错误是“'this'对象在其所有字段都分配给之前不能使用”。我知道这是结构的标准过程:必须从结构的构造函数中直接(而不是通过属性的 set 访问器)分配任何属性的支持字段。

一种解决方案是使用显式支持字段:

struct MyStruct
{ 
    public MyStruct(int size)
    {
        _size = size;
    }

    private int _size;

    public int Size
    {
        get { return _size; }
        set { _size = value; }
    }
}

(请注意,VB.NET 不会有这个问题,因为在 VB.NET 中,所有字段在首次创建时都会自动初始化为 0/null/false。)

在 C# 中使用带有结构的自动属性时,这似乎是一个不幸的限制。从概念上考虑,我想知道这是否不是一个合理的地方,允许在结构的构造函数中调用属性集访问器的异常,至少对于自动属性?

这是一个小问题,几乎是一个极端情况,但我想知道其他人对此有何看法......

4

3 回答 3

82

从 C# 6 开始:这不再是问题


Becore C# 6,您需要调用默认构造函数才能使其工作:

public MyStruct(int size) : this()
{
    Size = size;
}

这里更大的问题是你有一个可变结构。这从来都不是一个好主意。我会做到的:

public int Size { get; private set; }

在技​​术上不是一成不变的,但足够接近。

使用最新版本的 C#,您可以对此进行改进:

public int Size { get; }

现在只能在构造函数中分配。

于 2009-01-07T14:17:23.533 回答
10

您可以通过首先调用默认构造函数来解决此问题:

struct MyStruct 
{
    public MyStruct(int size) : this() 
    {
        this.Size = size; // <-- now works
    }

     public int Size { get; set; }
}
于 2009-01-07T14:21:08.487 回答
8

这个问题的另一个模糊解决方法是在托管可扩展性框架Tuple的临时类中发现的(通过Krzysztof Koźmic):

public struct TempTuple<TFirst, TSecond>
{
    public TempTuple(TFirst first, TSecond second)
    {
        this = new TempTuple<TFirst, TSecond>(); // Kung fu!
        this.First = first;
        this.Second = second;
    }

    public TFirst First { get; private set; }
    public TSecond Second { get; private set; }

(来自 Codeplex 的完整源代码:Tuple.cs

我还注意到CS0188的文档已更新为添加:

如果您在尝试初始化结构构造函数中的属性时看到此错误,解决方案是更改构造函数参数以指定支持字段而不是属性本身。结构中应避免使用自动实现的属性,因为它们没有支持字段,因此无法从构造函数以任何方式初始化。

所以我认为这意味着官方指导是在你遇到这个问题时在你的结构中使用旧样式的属性,这可能比目前探索的其他两个替代方案中的任何一个都不那么晦涩(并且更易读)。

于 2009-02-11T05:50:18.773 回答