Дизайн класса C # - выставлять переменные для чтения, но не для настройки - PullRequest
0 голосов
/ 01 мая 2010

У меня есть класс многоугольника, который хранит список Microsoft.Xna.Framework.Vector2 в качестве вершин многоугольника. После создания многоугольника я бы хотел, чтобы другие классы могли читать положение вершин, но не изменять их.

В настоящее время я выставляю вершины через это поле:

/// <summary>
/// Gets the vertices stored for this polygon.
/// </summary>
public List<Vector2> Vertices
{
    get { return _vertices; }
}
List<Vector2> _vertices;

Однако вы можете изменить любую вершину, используя такой код:

Polygon1.Vertices[0] = new Vector2(0, 0);

или

Polygon1.Vertices[0].X = 0;

Как я могу ограничить другие классы, чтобы они могли только читать свойства этих вершин и не могли устанавливать новый для моего Списка? Единственное, о чем я могу думать, это передать копию классам, которые ее запрашивают.

Обратите внимание, что Vector2 - это структура, которая является частью структуры XNA, и я не могу ее изменить.

Спасибо.

Ответы [ 4 ]

6 голосов
/ 01 мая 2010

Имейте интерфейс только для чтения на вашем типе (однако, так как это встроенный тип), и раздайте версию в ReadOnlyCollection для.

public ReadOnlyCollection<IReadOnlyVector2> Vertices
{
    get { return (from v in _vertices 
                  select new DerivedVector2 { WrappedVector2 = v })
                 .Cast<IReadOnlyVector2>().ToList().AsReadOnly(); 
     }
}
List<Vector2> _vertices;

interface IReadOnlyVector2 {
 .. only RO getters and no setters
}

class DerivedVector2 : IReadOnlyVector2{
    public Vector2 WrappedVector2 { get; internal set;} 
.
.
.

}

0 голосов
/ 26 мая 2010

Еще один вариант с использованием доходности:

List<Vector2> _vertices;
public IEnumerable<Vector2> Vertices
{
    get
    {
        foreach (Vector2 vec in _vertices)
            yield return vec;
    }
}

Хотя я бы, наверное, сказал, что ответ Криска самый лучший ...

Рядом с _vertices.AsReadOnly (), конечно: D

0 голосов
/ 01 мая 2010

Просто хотел предложить вариант Привет, ответ .

public IEnumerable<IReadOnlyVector2> Vertices
{
    get
    {
        return from v in _vertices 
               select (IReadOnlyVector2)new DerivedVector2(v);
    }
}

Возвращение IEnumerable<> изначально доступно только для чтения, поскольку клиенты могут только перечислять, а не изменять. Кроме того, упрощенное выражение LINQ удаляет три дополнительных шага, которые, по моему мнению, излишни.

Стоит упомянуть эффект .ToList(). Он создаст новый экземпляр List<> и скопирует все векторы в этот список. Побочным эффектом этого является то, что клиенты, хранящие ссылку, будут иметь список, который фактически не синхронизирован с оригиналом. С другой стороны, если мы возвращаем выражение LINQ напрямую, перечисление возвращенной ссылки всегда будет перечислять внутренний список.

0 голосов
/ 01 мая 2010

Делайте так, как часто делает XNA Framework:

private List<Vector2> myVectors = new List<Vector2>();

public Vector2[] Vertices { get { return myVectors.ToArray(); } }
...