通过属性重新分配结构的成员变量

时间:2012-07-29 20:44:06

标签: c# properties struct

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

    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已经使用无参数默认构造函数进行了新的操作。现在,这是奇怪的部分。当我删除权重的set属性的自定义实现并将其替换为泛型{get;组;任务完美无瑕。

有谁知道这里发生了什么?这是一个结构的怪癖,可以适用于类吗?

4 个答案:

答案 0 :(得分:3)

您已在_weight媒体资源_weight方法中对set媒体资源进行递归调用。

答案 1 :(得分: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
}

答案 2 :(得分:1)

_weight属性的Setter正在递归调用它自己并导致StackOverFlow异常

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

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;
        }
     }

答案 3 :(得分:1)

在_weight的setter中,你试图设置_weight,这样就会产生无限递归。

尝试类似的事情(不包括零售和运费的额外逻辑):

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

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

还要注意使用的命名约定,字段(_weight)以下划线为前缀,并且应始终为私有。外部世界使用属性(权重)与字段交互。整个.NET框架中都存在此模式,有关详细信息,请参阅What is the difference between a Field and a Property in C#?