C#中的封装问题

发布于 2024-11-08 02:11:33 字数 1246 浏览 4 评论 0原文

我在 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

烟酒忠诚 2024-11-15 02:11:33

对于场景 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.

海夕 2024-11-15 02:11:33

场景 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:

您要么需要在 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 make OtherClass a class and not a struct or you do something along those lines:

struct OtherClass
{
    public int XYZ { get; }

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

    public OtherClass AddToXYZ(int count)
    {
         return new OtherClass(this.XYZ + count);
    }
}

Then you can do

myClass.otherClass = myClass.otherClass.AddToXYZ(1);

Scenario 2:

You either need to implement IEnumerable on trksegType to enumerate over trkpt or actually access trkpt 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.

累赘 2024-11-15 02:11:33

(您确实不应该将两个问题合二为一。)

场景 1

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

发生此错误的原因是 OtherClass 不是类,而是结构体 - 也称为值类型。这意味着访问 MyClass.otherClass 会复制值而不是返回引用。您将修改此副本,这是毫无意义的。编译器会捕获这一点,因为它始终是一个错误并且永远没有用处。

场景 2

foreach (wptType way in trk.trkseg[i])

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

也许您想写:

foreach (wptType way in trk.trkseg[i].trkpt)

因为trkptwptType的数组。 (如果您使用更有意义的变量名称而不是毫无意义的奇怪字母组合,您可能会更快发现此错误。)

(You really shouldn’t post two questions in one.)

Scenario 1

Cannot Modify the return value of 'MyClass.otherClass' because it is not a variable.

This error happens because OtherClass is not a class, but a struct — also called a value type. This means that accessing MyClass.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

foreach (wptType way in trk.trkseg[i])

You haven’t told us what trkseg[i] is, but if it is of the type trksegType, then the answer is: because trksegType doesn’t allow any enumeration. It does not implement IEnumerable, IEnumerable<T>, nor does it have a GetEnumerator method of its own.

Perhaps you meant to write:

foreach (wptType way in trk.trkseg[i].trkpt)

because trkpt is an array of wptType. (You might have found this error sooner if you used more meaningful variable names instead of weird combinations of letters that make no sense.)

不奢求什么 2024-11-15 02:11:33

我看不出你的第一个例子有什么问题 - 所以请仔细检查错误的示例是否确实存在,如果没有则更正。

在第二个实例中,您似乎正在尝试迭代 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文