自动属性和结构体

9

我想了解以下C#代码:

struct Structure
{
    public Structure(int a, int b)
    {
        PropertyA = a;
        PropertyB = b;
    }
    public int PropertyA { get; set; }
    public int PropertyB { get; set; }
}

出现错误:“在分配完所有字段之前无法使用'this'对象”。对于类似的类,它可以编译而没有任何问题。

通过重构以下内容可以使其正常工作:

struct Structure
{
    private int _propertyA;
    private int _propertyB;

    public Structure(int a, int b)
    {
        _propertyA = a;
        _propertyB = b;
    }

    public int PropertyA
    {
        get { return _propertyA; }
        set { _propertyA = value; }
    }

    public int PropertyB
    {
        get { return _propertyB; }
        set { _propertyB = value; }
    }
}

但是,我认为引入自动属性到C#的整个目的是避免编写后续代码。这是否意味着自动属性对结构体不相关?


你使用的是哪个版本的 .Net? - Thom Wiggers
16
每次你写可变的结构体,就会有人哭泣。 - Marc Gravell
@TheGuyOfDoom - 没关系...在任何情况下行为都是相同的;这是C# 3.0编译器的一个特性,而“修复”方法就像Stefan所说的那样。 - Marc Gravell
1
可能是 Automatic Properties and Structures Don't Mix? 的重复问题。 - nawfal
请注意,在C# 6中,这不再是一个问题。 - Marc Gravell
3个回答

21
在C# 6中,这个简单地消失了;问题中的代码可以正常编译。
虽然Stefan给出了回答解决了问题,但我必须告诫您不要使用可变结构体 - 它会到您。 可变结构体是有害的。
我个人认为,这里的“正确”修复方法很简单:
struct Structure
{
    public Structure(int a, int b)
    {
        propertyA = a;
        propertyB = b;
    }
    private readonly int propertyA, propertyB;
    public int PropertyA { get { return propertyA; } }
    public int PropertyB { get { return propertyB; } }
}

3
我会用 PropertyA { get; private set; } 来实现。使用 readonly 几乎不会带来什么好处——避免设置属性超过一次几乎总是微不足道的。如果您不使用 readonly,仍然可以使用自动实现的属性,因此问题仍然存在。 - Joren
3
@Joren - 它表达了我们的意图 ;),避免了不得不调用 :this() 的烦恼。 - Marc Gravell
@Joren 对于那些未来可能会遇到这个问题的人:如果您尝试从构造函数内部设置属性,则该建议无法编译。 - Eric
@Eric - 编译没问题吗?struct Foo { Foo(int x) : this() { X = x; } public int X { get; private set; } - Joren
@MarcGravell:值得庆幸的是,C# 6 还允许您使用只读自动属性,最终消除了声明和使用显式后备字段的痛苦。我一直避免使用 readonly,因为它所做的大部分工作只是使我的对象变得不够简洁。 - Joren
显示剩余3条评论

15

你需要先调用默认构造函数,像这样:

struct Structure
{
    public Structure(int a, int b) : this()
    {
        PropertyA = a;
        PropertyB = b;
    }
    public int PropertyA { get; set; }
    public int PropertyB { get; set; }
}

请注意,在C#6中不再是这种情况。 - Marc Gravell

8

正如您所见,在构造函数中引用PropertyA时,您正在访问this对象,但编译器不会允许这样做,因为您的字段尚未初始化。

为了解决这个问题,您需要找到一种初始化字段的方法。其中一种方法是使用示例中的方法:如果您不使用自动属性,则字段是明确的,您可以初始化它们。

另一种方法是使您的构造函数调用另一个构造函数来初始化字段。结构体始终隐式具有一个无参数构造函数,该构造函数将其字段初始化为零,因此请使用它:

public Structure(int a, int b)
    : this()
{
    PropertyA = a;
    PropertyB = b;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接