Запретить публичное добавление и удаление списка

Я написал эту функцию, которая возвращает связанный список разделенных строк конкретным разделителем. Чистый свободный паскаль без модулей.

Program split_f;

type
    PTItem = ^TItem;
    TItem = record
        str : string;
        next : PTItem;
    end;

var
    s : string;
    strs : PTItem;

procedure split(str : string;delim : char;var list : PTItem);
var
    i : integer;
    buff : PTItem;
begin
    new(list);
    buff:= list;
    buff^.str:='';
    buff^.next:=nil;

    for i:=1 to length(str) do begin
        if (str[i] = delim) then begin
            new(buff^.next);
            buff:=buff^.next;
            buff^.str := '';
            buff^.next := nil;
        end
        else
        buff^.str:= buff^.str+str[i];
    end;
end;

procedure print(var list:PTItem);
var
    buff : PTItem;
begin
    buff := list;
    while buff<>nil do begin
        writeln(buff^.str);
        buff:= buff^.next;
    end;
end;

begin

    s := 'Hi;how;are;you?';

    split(s, ';', strs);
    print(strs);


end.
13
задан Aaginor 16 June 2010 в 12:01
поделиться

8 ответов

Если вы передадите вызывающему абоненту список List , вы не сможете это контролировать; вы даже не можете создать подкласс List , поскольку добавление / удаление не являются виртуальными .

Вместо этого я бы предоставил данные как IEnumerable :

private readonly List<MyClass> children = new List<MyClass>();
public void AddChild(MyClass child) {...}
public void RemoveChild(MyClass child) {...}
public IEnumerable<MyClass> Children {
    get {
        foreach(var child in children) yield return child;
    }
}

( yield return не позволяет им просто преобразовать его)

Вызывающий все еще может используйте foreach на . Дети , и благодаря LINQ они могут делать и все другие забавные вещи ( Где , Сначала и т. д.) .

30
ответ дан 1 December 2019 в 06:08
поделиться
using System.Collections.ObjectModel;

public class MyClass
{
    private List<MyClass> children;

    public ReadOnlyCollection<MyClass> Children
    {
        get
        {
            return new ReadOnlyCollection<MyClass>(children);
        }
    }
}
1
ответ дан 1 December 2019 в 06:08
поделиться

Сделайте список частным и создайте общедоступные методы для доступа к его содержимому извне класса.

public class MyClass
{
    public MyClass Parent { get; private set; }

    private List<MyClass> _children = new List<MyClass>();
    public IEnumerable<MyClass> Children
    {
        get
        {
            // Using an iterator so that client code can't access the underlying list
            foreach(var child in _children)
            {
                yield return child;
            }
        }
    }

    public void AddChild(MyClass child)
    {
        child.Parent = this;
        _children.Add(child);
    }

    public void RemoveChild(MyClass child)
    {
        _children.Remove(child);
        child.Parent = null;
    }
}

Кстати, избегайте объявления публичных полей, потому что вы не можете контролировать, что клиентский код делает с ними.

3
ответ дан 1 December 2019 в 06:08
поделиться

Вы можете инкапсулировать список в классе, сделав его частным, и предложить его как ReadOnlyCollection:

public class MyClass {

  public MyClass Parent { get; private set; };

  private List<MyClass> _children;

  public ReadOnlyCollection<MyClass> Children {
    get { return _children.AsReadOnly(); }
  }

  public void AddChild(MyClass item) {
    item.Parent = this;
    _children.Add(item);
  }

  public void DeleteChild(MyClass item) {
    item.Parent = null;
    _children.Remove(item);
  }

}

Вы можете сделать Parent свойством с частным установщиком , таким образом он не может быть изменен извне, но методы AddChild и DeleteChild могут его изменить.

0
ответ дан 1 December 2019 в 06:08
поделиться

Помимо реализации собственного IList вы можете вернуть ReadOnlyCollection.

public MyClass
{
    public MyClass Parent;

    private List<MyClass> children;
    public ReadOnlyCollection<MyClass> Children
    {
        get { return children.AsReadOnly(); }
    }
}
14
ответ дан 1 December 2019 в 06:08
поделиться

Expose the list as IEnumerable

6
ответ дан 1 December 2019 в 06:08
поделиться

Вам не нужно повторно реализовывать IList, просто инкапсулируйте List в класс, и предоставьте свои собственные функции Add и Delete, которые позаботятся о добавлении и установке необходимых свойств.

Возможно, вам придется создать свой собственный перечислитель, если вы хотите перечислять список.

0
ответ дан 1 December 2019 в 06:08
поделиться

Use List(T).AsReadOnly().

http://msdn.microsoft.com/en-us/library/e78dcd75.aspx

Возвращает только для чтения IList<(Of <(T>)>) обертку для текущей коллекции.

Доступно с версии .NET 2.0.

0
ответ дан 1 December 2019 в 06:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: