[英]Encapsulation questions in C#
我在使用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 (wptType way in trk.trkseg[i])
我被告知-foreach语句不能对'trksegType'类型的变量进行操作,因为'trksegType'不包含'GetEnumerator'的公共定义
即使数组应隐式允许枚举。
任何人都可以解释正在发生的事情以及我可以做些什么来解决此问题,同时仍然保持最佳实践。
对于场景1,我怀疑OtherClass已被定义为结构。 从属性访问器访问结构时,将创建并返回该结构的新副本(结构为值类型 )。 更改此新副本上的属性不会影响原始结构。
C#编译器检测到此错误,并引发该稍微模糊的错误。
方案1:
原因很可能是因为您的OtherClass
是一个结构而不是一个类。 价值语义学有些棘手,可变的价值类型被认为是有害的。 因此,您要么想让OtherClass
成为一个类而不是一个struct,要么按照以下方式做一些事情:
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:
你要么需要实现IEnumerable
上trksegType
列举了trkpt
或实际访问trkpt
的枚举。
一般来说:
您通过其他对象访问对象在两种情况下都违反了封装。 在这里看看: http : //www.csharp-station.com/Tutorials/lesson19.aspx
您还应该考虑为对象使用更好(更明确)的名称。 mttng vwls ds nt ncrs rdblty。
我看不到您的第一个示例有什么问题-因此,请仔细检查该错误确实有效的示例,如果没有,请更正。
在第二个实例中,您似乎正在尝试迭代trksegType的实例,而不是所包含的trkpt属性。 尝试使用foreach (wptType way in trk.trkseg[i].trkpt)
。
(您真的不应该将两个问题合而为一。)
无法修改'MyClass.otherClass'的返回值,因为它不是变量。
发生此错误是因为OtherClass
不是类,而是结构—也称为值类型 。 这意味着访问MyClass.otherClass
复制该值,而不是返回引用。 您将修改此副本,这将毫无意义。 编译器抓住了这一点,因为它始终是一个错误,并且从没有使用过。
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
。 (如果您使用更有意义的变量名而不是毫无意义的字母组合,则可能会更快地发现此错误。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.