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:
foreach (wptType way in trk.trkseg[i])
我被告知 - foreach 语句无法对“trksegType”类型的变量进行操作,因为“trksegType”不包含“GetEnumerator”的公共定义,
即使数组应该隐式允许枚举。
谁能解释一下发生了什么以及我可以采取哪些措施来解决这个问题,同时仍然保持最佳实践。
I'm having some problems with encapsulation in C#. There are two specific scenarios that are causing me problems and I believe the issue is related.
Scenario #1
I have a class definition that looks something like this
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; }
}
}
If I then try and do something like this in a new piece of code
MyClass theClass = new MyClass();
theClass.otherClass.XYZ += 1;
I get told Cannot Modify the return value of 'MyClass.otherClass' because it is not a variable.
Scenario 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;
}
}
}
If I now try and foreach through the wptType array:
foreach (wptType way in trk.trkseg[i])
I get told - foreach statement cannot operate on variables of type 'trksegType' because 'trksegType' does not contain a public definition for 'GetEnumerator'
Even though an array should implicitly allow enumeration.
Can anyone explain what's going on and what I can do to get around this problem, whilst still maintaining best practices.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
对于场景 1, 我怀疑 OtherClass 已被定义为结构体。当从属性访问器访问结构时,会创建并返回该结构的新副本(结构是值类型< /a>)。更改此新副本上的属性不会对原始结构产生影响。
C# 编译器会检测到这一点并引发那个稍微模糊的错误。
For scenario 1, I suspect that OtherClass has been defined as a struct. When a struct is accessed from a property accessor a new copy of the struct is created and returned (structs are value types). Changing a property on this new copy will have no effect on the original struct.
The C# compiler detects this and raises that slightly obscure error.
场景 1:
原因很可能是因为您的
OtherClass
是一个结构体而不是一个类。值语义有点棘手,可变值类型被认为是有害的。因此,您要么想让OtherClass
成为一个类而不是一个结构体,要么按照这些思路做一些事情:然后您可以执行
场景 2:
您要么需要在
IEnumerable
上实现IEnumerable
code>trksegType 枚举trkpt
或实际访问trkpt
进行枚举。一般情况:
在这两种情况下,通过其他对象访问对象都违反了封装。看看这里:http://www.csharp-station.com/Tutorials/lesson19。 aspx
您还应该考虑为您的对象使用更好(更明确)的名称。 mttng vwls ds nt ncrs rdblty。
Scenario 1:
The reason is very likely because your
OtherClass
is a struct and not a class. Value sematics are a bit tricky and mutable value types are considered harmful. So you either want to makeOtherClass
a class and not a struct or you do something along those lines:Then you can do
Scenario 2:
You either need to implement
IEnumerable
ontrksegType
to enumerate overtrkpt
or actually accesstrkpt
for the enumeration.In General:
You have violated encapsulation in both scenarios by accessing objects through other objects. Have a look here: http://www.csharp-station.com/Tutorials/lesson19.aspx
You also should consider using better (more explicit) names for your objects. mttng vwls ds nt ncrs rdblty.
(您确实不应该将两个问题合二为一。)
场景 1
发生此错误的原因是
OtherClass
不是类,而是结构体 - 也称为值类型。这意味着访问MyClass.otherClass
会复制值而不是返回引用。您将修改此副本,这是毫无意义的。编译器会捕获这一点,因为它始终是一个错误并且永远没有用处。场景 2
您还没有告诉我们
trkseg[i]
是什么,但如果它是trksegType
类型,那么答案是:因为trksegType
code> 不允许任何枚举。它不实现IEnumerable
、IEnumerable
,也没有自己的GetEnumerator
方法。也许您想写:
因为
trkpt
是wptType
的数组。 (如果您使用更有意义的变量名称而不是毫无意义的奇怪字母组合,您可能会更快发现此错误。)(You really shouldn’t post two questions in one.)
Scenario 1
This error happens because
OtherClass
is not a class, but a struct — also called a value type. This means that accessingMyClass.otherClass
copies the value instead of returning a reference. You would be modifying this copy, which would be pointless. The compiler catches this because it is always a bug and never useful.Scenario 2
You haven’t told us what
trkseg[i]
is, but if it is of the typetrksegType
, then the answer is: becausetrksegType
doesn’t allow any enumeration. It does not implementIEnumerable
,IEnumerable<T>
, nor does it have aGetEnumerator
method of its own.Perhaps you meant to write:
because
trkpt
is an array ofwptType
. (You might have found this error sooner if you used more meaningful variable names instead of weird combinations of letters that make no sense.)我看不出你的第一个例子有什么问题 - 所以请仔细检查错误的示例是否确实存在,如果没有则更正。
在第二个实例中,您似乎正在尝试迭代 trksegType 的实例,而不是包含的 trkpt 属性。尝试使用
foreach(trk.trkseg[i].trkpt 中的 wptType 方式)
。I can't see anything wrong with your first example - so double check that the sample that errors really does and correct if not.
In the second instance, it looks like you're trying to iterate on an instance of trksegType, rather than the contained trkpt property. Try
foreach (wptType way in trk.trkseg[i].trkpt)
instead.