1

所以我有一个以下列方式定义的结构:

    public struct Item
{
    public string _name { get; set; }
    public double _weight
    {
        get 
        {
            return _weight;
        }
        set
        {
            _weight = value;

            //Shipping cost is 100% dependent on weight. Recalculate it now.
            _shippingCost = 3.25m * (decimal)_weight;

            //Retail price is partially dependent on shipping cost and thus on weight as well.  Make sure retail price stays up to date.
            _retailPrice = 1.7m * _wholesalePrice * _shippingCost;
        }
     }
    public decimal _wholesalePrice
    {
        get
        {
            return _wholesalePrice;
        }
        set
        {
            //Retail price is partially determined by wholesale price.  Make sure  retail price stays up to date.
            _retailPrice = 1.7m * _wholesalePrice * _shippingCost;
        }
    }
    public int _quantity { get; set; }
    public decimal _shippingCost { get; private set; }
    public decimal _retailPrice { get; private set; }


    public Item(string name, double weight, decimal wholesalePrice, int quantity) : this()
    {
        _name = name;
        _weight = weight;
        _wholesalePrice = wholesalePrice;
        _quantity = quantity;
    }
//More stuff

我在另一个类中也有一个 Item 实例。当我尝试通过以下命令调用 weight 属性时,程序崩溃:

currentUIItem._weight = formattedWeight;

未提供描述性错误。请注意,此时, currentUIItem 已使用无参数默认构造函数进行了更新。现在,这是奇怪的部分。当我删除 weight 的 set 属性的自定义实现并将其替换为通用 { get; 放; },作业完美无缺。

有谁知道这里发生了什么?这是一个可以在类中正常工作的结构怪癖吗?

4

4 回答 4

3

_weight您在_weight属性的方法中有对属性的递归调用set

于 2012-07-29T20:50:46.447 回答
2

看起来这会导致 StackOverflowException 因为您有无限递归。

如果你在你的设置器中放置一个断点:

public double _weight
{
    set
    {
        _weight = value;
    }
 }

您将看到断点继续被命中。这是因为 setter 试图为 _weight 设置一个值。但是 _weight 不是一个变量......所以当你尝试设置它的值时,你只是回调到 setter 方法。这继续无限地发生。这同样适用于 _wholesalePrice 属性......你可能想要更像这样的东西:

public struct Item
{
    public string _name { get; set; }

    private double _weightInternal;
    public double _weight
    {
        get 
        {
            return _weightInternal;
        }
        set
        {
            _weightInternal = value;

            //Shipping cost is 100% dependent on weight. Recalculate it now.
            _shippingCost = 3.25m * (decimal)_weightInternal;

            //Retail price is partially dependent on shipping cost and thus on weight as well.  Make sure retail price stays up to date.
            _retailPrice = 1.7m * _wholesalePriceInternal * _shippingCost;
        }
    }

    private decimal _wholesalePriceInternal;
    public decimal _wholesalePrice
    {
        get
        {
            return _wholesalePriceInternal;
        }
        set
        {
            //Retail price is partially determined by wholesale price.  Make sure  retail price stays up to date.
            _wholesalePriceInternal = value;
            _retailPrice = 1.7m * _wholesalePriceInternal * _shippingCost;
        }
    }
    public int _quantity { get; set; }
    public decimal _shippingCost { get; private set; }
    public decimal _retailPrice { get; private set; }


    public Item(string name, double weight, decimal wholesalePrice, int quantity) : this()
    {
        _name = name;
        _weightInternal = weight;
        _wholesalePriceInternal = wholesalePrice;
        _quantity = quantity;
    }
    //More stuff
}
于 2012-07-29T20:52:40.910 回答
1

属性的 Setter_weight递归调用自身并导致 StackOverFlow 异常

解决此问题的最简单方法是以这种方式为属性提供支持字段

private double  _weight;
public double Weight
    {
        get 
        {
            return _weight;
        }
        set
        {
            _weight = value;

            //Shipping cost is 100% dependent on weight. Recalculate it now.
            _shippingCost = 3.25m * (decimal)_weight;

            //Retail price is partially dependent on shipping cost and thus on weight as well.  Make sure retail price stays up to date.
            _retailPrice = 1.7m * _wholesalePrice * _shippingCost;
        }
     }
于 2012-07-29T20:53:51.757 回答
1

在 _weight 的设置器中,您试图设置 _weight,因此这会导致无限递归。

尝试类似(不包括您对零售和运输成本的额外逻辑):

private double _weight;
public double Weight
{
     get { return _weight; }
     set { _weight = value; }
}

using 只是get; set;告诉编译器自动为您生成一个支持字段,并且与上面的代码具有相同的效果。

还要注意使用的命名约定,字段 (_weight) 带有下划线前缀,并且应该始终是私有的。外部世界使用属性(权重)与字段交互。这种模式在整个 .NET 框架中都存在,请参阅C# 中的字段和属性有什么区别?了解更多信息。

于 2012-07-29T20:55:20.003 回答