Вопросы инкапсуляции в C # - PullRequest
1 голос
/ 18 мая 2011

У меня проблемы с инкапсуляцией в 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;
        }
    }
}

Если я сейчас попытаюсь выполнить foreach через массив wptType:

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

Мне сказали - оператор foreach не может работать с переменными типа 'trksegType', потому что 'trksegType' не содержит открытого определения для 'GetEnumerator'

Даже если массив должен неявно разрешать перечисление.

Может ли кто-нибудь объяснить, что происходит и что я могу сделать, чтобы обойти эту проблему, сохраняя при этом лучшие практики.

Ответы [ 4 ]

2 голосов
/ 18 мая 2011

Для сценария 1, Я подозреваю, что OtherClass был определен как структура. При обращении к структуре из средства доступа к свойствам создается и возвращается новая копия структуры (структуры имеют типы значений ). Изменение свойства этой новой копии не повлияет на исходную структуру.

Компилятор C # обнаруживает это и вызывает слегка скрытую ошибку.

2 голосов
/ 18 мая 2011

Сценарий 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 на trksegType для перечисления по trkpt, либо получить доступ к trkpt для перечисления.

В общем:

Вы нарушилиинкапсуляция в обоих сценариях путем доступа к объектам через другие объекты.Посмотрите здесь: http://www.csharp -station.com / Tutorials / lesson19.aspx

Вам также следует рассмотреть возможность использования более качественных (более явных) имен для ваших объектов.Mtng VWLS DS NT NCRS RDBLTY.

1 голос
/ 18 мая 2011

(Вы действительно не должны размещать два вопроса в одном.)

Сценарий 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. (Вы могли бы найти эту ошибку раньше, если бы использовали более значимые имена переменных вместо странных комбинаций букв, которые не имеют смысла.)

1 голос
/ 18 мая 2011

Я не вижу ничего плохого в вашем первом примере - так что дважды проверьте, что пример, который ошибки действительно делают, и исправьте, если нет.

Во втором случае похоже, что вы пытаетесь выполнить итерацию для экземпляра trksegType, а не для содержащегося в нем свойства trkpt. Попробуйте foreach (wptType way in trk.trkseg[i].trkpt) вместо.

...