Аннотация:
Рассказ о коллекциях в .NET Framework. Статья будет полезна как начинающим программистам, так и желающим более подробно изучить этот вопрос.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Коллекции в .NET Framework Class Library
От:
Аноним
Дата:
30.01.04 15:46
Оценка:
Hi Vlad, I attached source file, could suggest how to fix that problem, please ?
Thx, Dmitry MS
Сценарий:
Создается коллекция объектов типа А (тип А имеет вложенную коллекцию типов B). В конструктор типа А передается коллекция типов B, предопределяя стартовый набор типов B в каждом из объектов А (наследовать смысла нет — слишком раznije объекты). После добавления А в коллекцию над екземпляром А проводятся изменения (вызывается процедура Do, принимающая параметером А). Ета процедура меняет не только А, но также все уже имеущиеся в коллекции ехемпляри А, как будто бы ето к ним относится.
Есть идея, что это поведение обусловлено фактом передачи в конструктор А мастер коллекции, которая всегда передается по ссилке (disregard of ByVal or ByRef). Таким образом, все созданние екземпляры А имеют не независимие коллекции типов B, а ссылку на одну такую коллекцию, заданную при их создании.
Вопрос:
Как ограничить область применения преобразований над А — конкретним екземпляром, передаваемым в процедуру Ду.
Спасибо.
P.S. Source.
namespace Refs
{
/// <summary>
/// Summary description for Form1.
/// </summary>public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Button button1;
/// <summary>
/// Required designer variable.
/// </summary>private System.ComponentModel.Container components = null;
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
//
// TODO: Add any constructor code after InitializeComponent call
//
}
/// <summary>
/// Clean up any resources being used.
/// </summary>protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// button1
// this.button1.Location = new System.Drawing.Point(232, 128);
this.button1.Name = "button1";
this.button1.TabIndex = 0;
this.button1.Text = "button1";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// Form1
// this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(688, 365);
this.Controls.Add(this.button1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
}
#endregion/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void button1_Click(object sender, System.EventArgs e)
{
Master m = new Master();
m.PredefinedFieldSet.Add(new Field("MyPredefinedField"));
Detail d;
//adds 10 detial items into masterfor (int i =0; i < 10; i++) {
d = new Detail(m.PredefinedFieldSet);
m.Details.Add(d);
}
//assign values to detail items (expected from 1 to 10)
m.AssignValues();
foreach (Detail d2 in m.Details) {
MessageBox.Show(d2.DerivedSet[0].Value.ToString());
}
}
}
//classes
//Fieldpublic class Field
{
private int _someValue;
private string _name;
public Field(string Name)
{
_name = Name;
}
public int Value
{
get
{
return _someValue;
}
set
{
_someValue = value;
}
}
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
}
//Fields collectionpublic class FieldsCollection: CollectionBase
{
public int Add(Field Item)
{
return this.List.Add(Item);
}
public Field this[int Index]
{
get
{
return (Field) this.List[Index];
}
}
}
//Master objectpublic class Master
{
private FieldsCollection _predefinedSet = new FieldsCollection();
private DetailsCollection _detials = new DetailsCollection();
int i;
public FieldsCollection PredefinedFieldSet
{
get
{
return _predefinedSet;
}
}
public DetailsCollection Details
{
get
{
return _detials;
}
}
//problempublic void AssignValues() {
foreach (Detail d in this.Details) {
i = i + 1;
d.DerivedSet[0].Value = i;
}
}
}
//Detial objectpublic class Detail
{
private FieldsCollection _derivedSet = new FieldsCollection();
public Detail(FieldsCollection DerivedSet)
{
_derivedSet = DerivedSet;
}
public FieldsCollection DerivedSet
{
get
{
return _derivedSet;
}
}
}
//Details collectionpublic class DetailsCollection: CollectionBase
{
public int Add(Detail Item)
{
return this.List.Add(Item);
}
public Detail this[int Index]
{
get
{
return (Detail) this.List[Index];
}
}
}
}
Здравствуйте, <Аноним>, Вы писали:
А>Вопрос: А>Как ограничить область применения преобразований над А — конкретним екземпляром, передаваемым в процедуру Ду.
Незнаю насколько верно я понял вопрос. Может быть тут проблема в организации коллекций, а не в огранизчении?
... << RSDN@Home 1.1.3 beta 2 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
I can't prevent class, derived from CollectionBase from being passed ByRef... That's my problem. I though of ref/out, but it doesn't seem be to be useful in my case.
Eventually I've got it sorted by the way... The lesson I've learnt from that is you can't reuse literally ANYTHING except of primitve values from existing colleciton, unless you want your collection to share address space with it's orginator (with all consiquent problems)...
I've tryed to create new collection and re-populate it with items of existing one (thought it'll separate them) — not gonna work... By times it looked like a feaver...
The solution was to use primitve proveprites of each item and reacreate item themselvs, rather than set them as as children for brand new collection.
Здравствуйте, Чистяков Владислав (VladD2), Вы писали:
ЧВV>Статья:
ЧВV>Авторы: ЧВV> Чистяков Владислав (VladD2)
ЧВV>Аннотация: ЧВV>Рассказ о коллекциях в .NET Framework. Статья будет полезна как начинающим программистам, так и желающим более подробно изучить этот вопрос.
в новом framwork появится IList, IDictionary коллекция. Ну там доспуп (вставка, чтение, замена и удаление) будет по позиции как в IList и доступ по ключу как в IDictionary... послухам эта коллекция использоватся где в WEB гуе будет. не знаю как называется,
вот кодогенератор типизированной коллекции для любого фреймоврка
пример консольного вызова
generate.exe /Key:Guid /Item:String /Dictionary:My.Collections.StringListKeyedByGuid
Здравствуйте, IT, Вы писали:
AI>>так написал кодогенератор кодогенератора
IT>Так надо написать не просто кодогенератор кодогенератора, а кодогенератор кодогенератора с человеческим лицом.
Пожалуй, стоит написать кодогенератор, который кодогенерирует кодогенератор с человеческим лицом, чтобы он генерировал кодогенератор, который генерирует коллекции. Фухх.
Здравствуйте, mikа, Вы писали:
IT>>Так надо написать не просто кодогенератор кодогенератора, а кодогенератор кодогенератора с человеческим лицом.
M>Пожалуй, стоит написать кодогенератор, который кодогенерирует кодогенератор с человеческим лицом, чтобы он генерировал кодогенератор, который генерирует коллекции. Фухх.
да таких кодоненераторов и плагинов уже туева хуча.
Здравствуйте, VBez, Вы писали:
VB>Пасиба.
На будущее — типы значений возвращаемые энумератором обычно (но не всегда) совпадают с типом индексера. В частности у BitArray имеется:
public bool this[int index]
Главное исключение из этого правила — Dictionary, его энумератор возвращает DictionaryEntry.
SortedList
...
Как и Hashtable, SortedList является реализацией абстракции «словарь» (IDictionary), но, в отличие от хэш-таблицы, поддерживает упорядоченность данных. Достигается это за счет хранения ключей и данных в двух отсортированных массивах.
...
Что значат выделенные слова?
Вот такой пример показывает, что ключи отсортированы, но значения — нет.
SortedList h = new SortedList();
h.Add(2, "Second");
h.Add(3, "Third");
h.Add(1, "First");
h[4] = "fourth";
foreach(object s in h.Keys)
{
Console.WriteLine(s.ToString());
}
foreach(object s in h.Values)
{
Console.WriteLine(s.ToString());
}
Здравствуйте, VBez, Вы писали:
VB>В чем тайный смысл того, что у SortedList есть свойство Capacity, а у Hashtable — нету.
Вот так вот реализована она. Возможно логика была такой: "рехэш слишком дорогое удоволсьвие чтобы инициировать его вручную."
VB>Ведь насколько я понял это почти классы-близнецы. VB>
VB>Как и Hashtable, SortedList является реализацией абстракции «словарь» (IDictionary)...
Не совсем. Реализация у них координально разная. SortedList реализован на базе отсортированного массива, а Hashtable на базе однименного алгоритма. Причем я бы очень не советовал использовать SortedList вообще. Больно сильно тормозит. В этом же номере есть статья про реализацию Б-дерева/двухуровневого массива. Вот ее вместо SortedList очень эффективно применять.
... << RSDN@Home 1.1.3 beta 2 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VB>SortedList
VB>...
VB>Как и Hashtable, SortedList является реализацией абстракции «словарь» (IDictionary), но, в отличие от хэш-таблицы, поддерживает упорядоченность данных. Достигается это за счет хранения ключей и данных в двух отсортированных массивах.
VB>...
VB>Что значат выделенные слова?
Так читать нужно все предложение целиком. Попробую префразировать.
SortedList реализован на базе двух отсортированных массивов... Отсюда и стоит делать выводы о скоростных харктиристиках.
... << RSDN@Home 1.1.3 beta 2 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, orangy, Вы писали:
O>На будущее — типы значений возвращаемые энумератором обычно (но не всегда) совпадают с типом индексера. В частности у BitArray имеется: O>
O> public bool this[int index]
O>
O>Главное исключение из этого правила — Dictionary, его энумератор возвращает DictionaryEntry.
Ну, ему по другому кикак. На он и словарь.
А универсальным советом сдесь как всегда является просмотр исходников из Ротора или декомпиляция. Собственно при написании статьи эти два источника были использованы довольно интенсивно.
... << RSDN@Home 1.1.4 beta 2 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
ЧВV>Авторы: ЧВV> Чистяков Владислав (VladD2)
ЧВV>Аннотация: ЧВV>Рассказ о коллекциях в .NET Framework. Статья будет полезна как начинающим программистам, так и желающим более подробно изучить этот вопрос.
Статья хорошая, спасибо.
Один глюк нашел в статье: В программульке, которая считает слова, не учитывается последнее слово. Из цикла выходим, не проверив, заполнен ли наш StringBuilder. Это так, на всякий случай, может книгу по мотивам напишут
Кроме всего прочего, необходимо заметить, что для создания массива необходимо жестко задать его размер. В дальнейшем размер массива изменен быть не может. Причем, как уже говорилось выше, языками, входящими в .NET, поддерживаются только массивы с верхней границей, равной нулю. Массивы с верхней границей, отличной от нуля, поддерживаются только на уровне runtime-а, методами класса Array.