C# C语言中的封装问题#

C# C语言中的封装问题#,c#,enumeration,accessor,C#,Enumeration,Accessor,我在C#中的封装方面遇到了一些问题。有两种特定的情况会给我带来问题,我相信这是相关的 情景1 我有一个类似这样的类定义 class MyClass { private int _someField; private OtherClass _otherClass; public int someField { get { return _someField; } set { _someField = value; } } public OtherClas

我在C#中的封装方面遇到了一些问题。有两种特定的情况会给我带来问题,我相信这是相关的

情景1

我有一个类似这样的类定义

class MyClass
{
  private int _someField;
  private OtherClass _otherClass;

  public int someField
  {
    get { return _someField; }
    set { _someField = value; }
  }

  public OtherClass otherClass
  {
    get { return _otherClass; }
    set { _otherClass = value; }
  }

}
如果我尝试在一段新代码中执行类似的操作

MyClass theClass = new MyClass();

theClass.otherClass.XYZ += 1;
我被告知无法修改“MyClass.otherClass”的返回值,因为它不是变量

情景2#

我被告知-foreach语句无法对“trksegType”类型的变量进行操作,因为“trksegType”不包含“GetEnumerator”的公共定义

即使数组应该隐式允许枚举


有人能解释一下发生了什么,我能做些什么来解决这个问题,同时保持最佳实践。

我看不出您的第一个示例有任何错误-因此,请仔细检查错误的示例是否确实存在,如果没有,请更正


在第二个实例中,看起来您正在尝试迭代trksegType的实例,而不是包含的trkpt属性。请尝试使用
foreach(trk.trkseg[i].trkpt中的wptType-way)

我看不出您的第一个示例有任何错误,因此请仔细检查错误的示例是否确实存在,如果没有,请更正


在第二个实例中,看起来您正在尝试迭代trksegType的实例,而不是包含的trkpt属性。请尝试使用
foreach(trk.trkseg[i].trkpt中的wptType方式)

对于场景1,我怀疑其他类已定义为结构。当从属性访问器访问结构时,将创建并返回该结构的新副本(即结构)。更改此新副本上的属性不会对原始结构产生影响


C#编译器检测到这一点,并引发稍微模糊的错误

对于场景1,我怀疑OtherClass已被定义为结构。当从属性访问器访问结构时,将创建并返回该结构的新副本(即结构)。更改此新副本上的属性不会对原始结构产生影响

C#编译器检测到这一点,并引发稍微模糊的错误

场景1:

原因很可能是因为您的
OtherClass
是一个结构而不是类。值语义有点棘手,可变值类型被认为是有害的。因此,您要么希望将
OtherClass
设置为类而不是结构,要么按照以下思路进行操作:

struct OtherClass
{
    public int XYZ { get; }

    public OtherClass(int xyz)
    {
         XYZ = xyz;
    }

    public OtherClass AddToXYZ(int count)
    {
         return new OtherClass(this.XYZ + count);
    }
}
那你就可以了

myClass.otherClass = myClass.otherClass.AddToXYZ(1);
情景2:

您需要在
trksegType
上实现
IEnumerable
以枚举
trkpt
或实际访问
trkpt
以进行枚举

一般而言:

通过其他对象访问对象违反了这两种情况下的封装。请看这里:

<>你也应该考虑为对象使用更好的(更明确的)名称。mttng vwls ds nt NCR rdblty.

场景1:

原因很可能是因为您的
OtherClass
是一个结构而不是类。值语义有点棘手,可变值类型被认为是有害的。因此,您要么希望将
OtherClass
设置为类而不是结构,要么按照以下思路进行操作:

struct OtherClass
{
    public int XYZ { get; }

    public OtherClass(int xyz)
    {
         XYZ = xyz;
    }

    public OtherClass AddToXYZ(int count)
    {
         return new OtherClass(this.XYZ + count);
    }
}
那你就可以了

myClass.otherClass = myClass.otherClass.AddToXYZ(1);
情景2:

您需要在
trksegType
上实现
IEnumerable
以枚举
trkpt
或实际访问
trkpt
以进行枚举

一般而言:

通过其他对象访问对象违反了这两种情况下的封装。请看这里:

<>你也应该考虑为对象使用更好的(更明确的)名称。mttng vwls ds nt NCR rdblty.

(你真的不应该在一个问题中提出两个问题。)

情景1 无法修改“MyClass.otherClass”的返回值,因为它不是变量

发生此错误的原因是
OtherClass
不是类,而是结构-也称为值类型。这意味着访问MyClass.otherClass将复制该值,而不是返回引用。您将修改此副本,这将是毫无意义的。编译器捕捉到了这一点,因为它总是一个bug,从来没有用过

情景2 您没有告诉我们什么是
trkseg[i]
,但是如果它是
trksegType
类型,那么答案是:因为
trksegType
不允许任何枚举。它没有实现
IEnumerable
IEnumerable
,也没有自己的
GetEnumerator
方法

也许你想写:

foreach (wptType way in trk.trkseg[i].trkpt)
因为
trkpt
wptType
的数组。(如果使用更有意义的变量名,而不是毫无意义的奇怪字母组合,您可能会更快地发现此错误。)

(您真的不应该在一个问题中发布两个问题。)

情景1 无法修改“MyClass.otherClass”的返回值,因为它不是变量

发生此错误的原因是
OtherClass
不是类,而是结构-也称为值类型。这意味着访问MyClass.otherClass将复制该值,而不是返回引用。您将修改此副本,这将是毫无意义的。编译器捕捉到了这一点,因为它总是一个bug,从来没有用过

情景2 您没有告诉我们什么是
trkseg[i]
,但是如果它是
trksegType
类型,那么答案是:因为
trksegType
不允许任何枚举。它没有实现
IEnumerable
IEnumerable
,也没有自己的
GetEnumerator
方法

也许你想写:

foreach (wptType way in trk.trkseg[i].trkpt)
因为
trkpt
wptType
的数组。(如果使用更有意义的va,您可能会更快地发现此错误