C# 中的封装问题
本文关键字:问题 封装 | 更新日期: 2023-09-27 17:56:51
我在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#
public partial class trksegType
{
private wptType[] trkptField;
private extensionsType extensionsField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("trkpt")]
public wptType[] trkpt
{
get
{
return this.trkptField;
}
set
{
this.trkptField = value;
}
}
}
如果我现在尝试通过 wptType 数组进行 foreach:
foreach (wptType way in trk.trkseg[i])
我被告知 - foreach 语句不能对"trksegType"类型的变量进行操作,因为"trksegType"不包含"GetEnumerator"的公共定义
即使数组应该隐式允许枚举。
谁能解释一下发生了什么以及我可以做些什么来解决这个问题,同时仍然保持最佳实践。
对于场景 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
。
通常:
在这两种情况下,您都通过其他对象访问对象,从而违反了封装。看看这里: http://www.csharp-station.com/Tutorials/lesson19.aspx
您还应考虑为对象使用更好(更明确)的名称。 MTTNG VWLS DS NT NCRS rdblty.
(你真的不应该把两个问题放在一个问题上。
场景 1
无法修改 'MyClass.otherClass' 的返回值,因为它不是变量。
发生此错误是因为OtherClass
不是一个类,而是一个结构体(也称为值类型)。这意味着访问MyClass.otherClass
会复制值,而不是返回引用。您将修改此副本,这将毫无意义。编译器会捕获这一点,因为它始终是一个错误并且永远不会有用。
场景 2
foreach (wptType way in trk.trkseg[i])
您还没有告诉我们trkseg[i]
是什么,但如果它是 trksegType
类型,那么答案是:因为trksegType
不允许任何枚举。它不实现IEnumerable
、IEnumerable<T>
,也没有自己的GetEnumerator
方法。
也许你的意思是写:
foreach (wptType way in trk.trkseg[i].trkpt)
因为trkpt
是wptType
数组。(如果您使用更有意义的变量名称而不是没有意义的奇怪字母组合,您可能会更早发现此错误。
我看不出您的第一个示例有什么问题 - 因此请仔细检查错误是否确实存在并纠正错误。
在第二个实例中,看起来您正在尝试迭代 trksegType 的实例,而不是包含的 trkpt 属性。 请尝试foreach (wptType way in trk.trkseg[i].trkpt)
。