表达式是一个值,因此不能成为赋值的目标

3

今天我在使用一个结构体时遇到了一个问题,让我措手不及,希望有人能为我解惑。

我定义了一个结构体,就像这样:

public struct PaymentDetail
{
    public Decimal Amount{get;set;}
    public string CheckNumber{get;set;}
    public PaymentType PaymentType{get;set;}
}

我有一个包含以下信息的类

public class Transaction
{
    public PaymentDetail Payment{get;}
}

我有一个呈现模型,我想设置其中的底层属性,如下所示。

public class ViewModel
{
    public Decimal Amount
    {
        get{return _Transaction.PaymentDetail.Amount;}
        set
        {
             //This is the offending line of code
             _Transaction.PaymentDetail.Amount = value;
             RaisePropertyChanged("Amount");
        }
    }
}
“很奇怪的是,如果我将Payment属性改成公共字段,就可以让它正常工作,代码如下:”
public class Transaction
{
    public PaymentDetail Payment;
}

显然,我对结构体还有一些不理解,这导致了问题的出现。这是一个不好的想法吗?有更好的方法吗?我做错了什么?

2个回答

6
首先,不要使用可变结构体(即可以通过setter等方式在构造后更改值的结构体)。这是混淆的主要原因。 重点是,当您调用属性(如Payment)时,您会得到该值的副本(在您的本地堆栈区域中)。对于类来说,这是引用的副本(没有问题)。对于结构体,则是结构体本身的副本。对该值进行任何更改都将被丢弃,因此编译器已经防止了数据丢失。 当它是公共字段时,您正在直接更改原始值,这就是为什么它不介意的原因。但是,更改结构体确实不是一个好主意。 将PaymentDetail设置为类;这是正确的解决方案... 在.NET中,结构体不是"没有行为的对象" - 它们是"值类型"。像"货币/价值对"、"时间范围"等东西可能是有效的结构体 - 但不是PaymentDetail。

那么每次我改变结构体中的一个值,它都会清除其他值吗? - Micah
1
不是...只是你可能没有编辑你认为的PaymentDetail - 它会在你眨眼的时候克隆自己! - Marc Gravell

-3

可能是因为您将Payment公开为只读,没有setter。由于结构体是值类型,如果结构体是只读的,则不允许您在结构体上设置属性。

添加setter应该可以解决问题。

我还建议将PaymentDetail更改为类。我仅在非常基本的值时使用结构体。像这样具有三个属性的东西,特别是其中一个是字符串,应该是一个类。


添加一个 setter 方法并不能解决那个问题。 - Jim Mischel

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