Я написал эту функцию, которая возвращает связанный список разделенных строк конкретным разделителем. Чистый свободный паскаль без модулей.
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.
Если вы передадите вызывающему абоненту список 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 они могут делать и все другие забавные вещи ( Где
, Сначала
и т. д.) .
using System.Collections.ObjectModel;
public class MyClass
{
private List<MyClass> children;
public ReadOnlyCollection<MyClass> Children
{
get
{
return new ReadOnlyCollection<MyClass>(children);
}
}
}
Сделайте список частным и создайте общедоступные методы для доступа к его содержимому извне класса.
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;
}
}
Кстати, избегайте объявления публичных полей, потому что вы не можете контролировать, что клиентский код делает с ними.
Вы можете инкапсулировать список в классе, сделав его частным, и предложить его как 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
могут его изменить.
Помимо реализации собственного IList
вы можете вернуть ReadOnlyCollection
.
public MyClass
{
public MyClass Parent;
private List<MyClass> children;
public ReadOnlyCollection<MyClass> Children
{
get { return children.AsReadOnly(); }
}
}
Вам не нужно повторно реализовывать IList, просто инкапсулируйте List в класс, и предоставьте свои собственные функции Add и Delete, которые позаботятся о добавлении и установке необходимых свойств.
Возможно, вам придется создать свой собственный перечислитель, если вы хотите перечислять список.
Use List(T).AsReadOnly()
.
http://msdn.microsoft.com/en-us/library/e78dcd75.aspx
Возвращает только для чтения IList<(Of <(T>)>) обертку для текущей коллекции.
Доступно с версии .NET 2.0.