Здравствуйте, pnb, Вы писали:
pnb>Подскадите код как создать в C# динамический массив и изменить его размер.
Класс ArrayList тебе поможет
Re[2]: Динамический массив в C#
От:
Аноним
Дата:
18.02.05 16:30
Оценка:
Здравствуйте, wraithik, Вы писали:
W>Здравствуйте, pnb, Вы писали:
pnb>>Подскадите код как создать в C# динамический массив и изменить его размер.
W>Класс ArrayList тебе поможет
Не всегда.. мне вот не помог. В функции, которая должна собирать и возвращать типизированный массив, пришлось писать ресайз массива руками. Шаблонов-то нет в 1.1 ...
примерно так. поскольку проект строго на фреймворке 1.1, буду писать типизированные аррайлисты для value-типов, более одного раза используемых в массивах... поскольку массивы ни каким образом не приводятся к дургим типам, кроме прямого копирования... строка вида
my_string_array = (string[])my_object_array;
компилится, но всегда при исполнении генерирует ошибку.
Можно посмотреть как ArrayList сделан.
Если я не ошибаюсь, то там внутренний массив при необходимости всегда увеличивается в два раза.
И держится индекс последнего элемента.
Это дает плюс если происходит множественное "поштучное" добавление элементов.
Подскадите код как создать в C# динамический массив и изменить его размер.
ArrayList ar_list=new ArrayList();
sozdaetsya динамический массив размер 16 esli xo4esh ymen4shit razmer do nastoyashego delaesh ar_list.TrimToSize()
Свойство Count можно использовать в условии цикла типа for для доступа к элементам динамического массива. Например, в следующем цикле используется свойство Count объекта myArrayList, и выводятся значения элементов, которые хранятся в массиве myArrayList:
for (int counter=0; counter<myArrayList.Count; counter++)
{
Console.WriteLine(myArrayList[counter]);
}
Здравствуйте, Аноним, Вы писали:
А>// создаем массив необходимого типа А>int[] arr = new int[10]; А>... А>// увеличиваем массив на 22 элемента А>IncreaseLength(ref arr, 22);
А>public static void IncreaseLength(ref int[] arr, int delta) А>{ А> int[] tmp = new int[arr.Length + delta]; А> Array.Copy(arr, 0, tmp, 0, arr.Length); А> arr = tmp; А>}
Все хорошо, только это не изменение размера массива, а создание массива большего размера и присваивание ссылки на него ссылке на старый массив. А это как говорится, "две большие разницы".
Re: Динамический массив в C#
От:
Аноним
Дата:
21.02.05 11:28
Оценка:
Все хорошо, только это не изменение размера массива, а создание массива большего размера и присваивание ссылки на него ссылке на старый массив. А это как говорится, "две большие разницы".
Здравствуйте, Аноним, Вы писали:
А>Некорректно сформулирован вопрос. Его (размер) вообще нельзя изменять.
А>Тогда, может, надо было ответить автору вопроса, что "динамических массивов не бывает"?
Нет, в котексте заданного автором вопроса этот ответ не был бы безусловно верным, т.к. можно было предположить, что под словом массив автор понимае массив как структуру данных. В этом случае в качестве динамического массива вполне м. использовать ArrayList.
Но в контексте же твоего ответа ясно что ты трактуешь понятие массива как массив .Net, а массив в таком понимании динамическим не бывает.
Здравствуйте, Mika Soukhov, Вы писали:
MS>Эх, сколько вариантов решений. Осталось за малом — узнать, что конкретно вопрошал автор.
Если честно, то я перевожу классы из VCL на C#. В Delphi я использовал динамические массивы: SetLength и т.п. и не парился. Здесь же у меня уже голова болит от вариантов что тут понаписали.
Здравствуйте, pnb, Вы писали:
pnb>Если честно, то я перевожу классы из VCL на C#. В Delphi я использовал динамические массивы: SetLength и т.п. и не парился. Здесь же у меня уже голова болит от вариантов что тут понаписали.
Используй ArrayList и не мучайся. Все остальное видимо тебе использовать пока рано.
SetLength в Delphi внутри создавал новый массив и копировал туда старый!
Примерно так же будет, если использовать Array.Copy.
ArrayList же более родственный для делфового TList.
Все должно быть просто, очень просто, настолько просто — насколько это возможно! Оренбургское сообщество .NET разработчиков
Глупый пингвин робко прячет тело жирное в утесах.
Но в контексте же твоего ответа ясно что ты трактуешь понятие массива как массив .Net,
Я трактую понятие "массив" как некую структуру данных. Про класс .NET я так и пишу Array (см., например, http://www.gotdotnet.ru/Forums/DataWorks/122825.aspx).
создаётся новый объект, видно невооружённым взглядом.
Мой вопрос (более полно) звучал так:
А разве можно иначе изменить размер массива? (кроме как создать новый, большего размера и скопировать туда исходный массив).
Я не стал писать то, что было в скобках, так как код был уже приведён, и, как мне казалось, всем и так понятно, о чём идёт речь.
Здравствуйте, Евгений Веприков, Вы писали:
ЕВ>SetLength в Delphi внутри создавал новый массив и копировал туда старый! ЕВ>Примерно так же будет, если использовать Array.Copy.
Не совсем так. Так как менеджер памяти резервирует память, то если за выделенным куском массива есть свободное место то он просто дополняется. Это касается увеличения, а при уменьшнии (финализируются элементы если нужно). Свободная память возвращается менеджеру памяти.
Совсем другая логика
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Аноним, Вы писали:
А>Но в контексте же твоего ответа ясно что ты трактуешь понятие массива как массив .Net, А>Я трактую понятие "массив" как некую структуру данных. Про класс .NET я так и пишу Array (см., например, http://www.gotdotnet.ru/Forums/DataWorks/122825.aspx).
Нет, по твоему коду следует, что ты трактуешь это понятие именно как массив .Net, а не как структуру данных.
А>Мой вопрос (более полно) звучал так: А>А разве можно иначе изменить размер массива? (кроме как создать новый, большего размера и скопировать туда исходный массив).
На пальцах:
— Как заставить программиста работать лучше? (автора топика)
— Уволить его и нанять того, кто работает лучше. (Varg)
— Но это уже будет другой программист? (Lloyd)
Ты видимо не понимаешь чем отличаются массив (программист) от ссылки на него (позиция программиста). При создании нового массива ты создаешь новый массив, а старый массив остается прежнего размера. А то что ты ссылку на новый массив сохраняешь в ссылке на старый погоды не делает. Подумай о том, что кто-то может все еще ссылаться на старый массив и твое якобы "изменение" массива его никак не коснется.
Re[6]: Динамический массив в C#
От:
Аноним
Дата:
21.02.05 15:26
Оценка:
Не совсем так. Так как менеджер памяти резервирует память, то если за выделенным куском массива есть свободное место то он просто дополняется. Это касается увеличения, а при уменьшнии (финализируются элементы если нужно). Свободная память возвращается менеджеру памяти.
Совсем другая логика
Вы видели исходники?
Все должно быть просто, очень просто, настолько просто — насколько это возможно! Оренбургское сообщество .NET разработчиков
Глупый пингвин робко прячет тело жирное в утесах.
Здравствуйте, Евгений Веприков, Вы писали:
ЕВ>Не совсем так. Так как менеджер памяти резервирует память, то если за выделенным куском массива есть свободное место то он просто дополняется. Это касается увеличения, а при уменьшнии (финализируются элементы если нужно). Свободная память возвращается менеджеру памяти. ЕВ>Совсем другая логика ЕВ> ЕВ>Вы видели исходники?
Конечно
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
и солнце б утром не вставало, когда бы не было меня
Re[7]: Динамический массив в C#
От:
Аноним
Дата:
21.02.05 16:11
Оценка:
Здравствуйте, Serginio1, Вы писали:
ЕВ>>SetLength в Delphi внутри создавал новый массив и копировал туда старый! ЕВ>>Примерно так же будет, если использовать Array.Copy. S> Не совсем так. Так как менеджер памяти резервирует память, то если за выделенным куском массива есть свободное место то он просто дополняется. Это касается увеличения, а при уменьшнии (финализируются элементы если нужно). Свободная память возвращается менеджеру памяти. S> Совсем другая логика
Если исходить из исходников, то это не так:
public virtual void set_Capacity(int value)
{
if (value == this._items.Length)
{
return;
}
if (value < this._size)
{
throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity"));
}
if (value > 0)
{
object[] objArray1 = new object[value];
if (this._size > 0)
{
Array.Copy(this._items, 0, objArray1, 0, this._size);
}
this._items = objArray1;
}
else
{
this._items = new object[0x10];
}
}
Если я не так вас понял, можно поподробнее расписать поведение этого чудного менеджера памяти?
Здравствуйте, <Аноним>, Вы писали:
А>Здравствуйте, Serginio1, Вы писали:
ЕВ>>>SetLength в Delphi внутри создавал новый массив и копировал туда старый! ЕВ>>>Примерно так же будет, если использовать Array.Copy. S>> Не совсем так. Так как менеджер памяти резервирует память, то если за выделенным куском массива есть свободное место то он просто дополняется. Это касается увеличения, а при уменьшнии (финализируются элементы если нужно). Свободная память возвращается менеджеру памяти. S>> Совсем другая логика
А>Если я не так вас понял, можно поподробнее расписать поведение этого чудного менеджера памяти?
Не ну в нативном Delphi такого нет. http://gzip.rsdn.ru/article/Delphi/dynarrays.xml#ENA
procedure DynArraySetLength(var a: Pointer; typeInfo: Pointer; dimCnt: Longint; lengthVec: PLongint);
var
i: Integer;
newLength, oldLength, minLength: Longint;
elSize: Longint;
neededSize: Longint;
p, pp: Pointer;
begin
p := a;
// Fetch the new length of the array in this dimension, and the old length
newLength := PLongint(lengthVec)^;
if newLength <= 0 then
begin
if newLength < 0 then
Error(reRangeError);
DynArrayClear(a, typeInfo);
exit;
end;
oldLength := 0;
if p <> nil then
begin
Dec(PLongint(p));
oldLength := PLongint(p)^;
Dec(PLongint(p));
end;
// Calculate the needed size of the heap object
Inc(PChar(typeInfo), Length(PDynArrayTypeInfo(typeInfo).name));
elSize := PDynArrayTypeInfo(typeInfo).elSize;
if PDynArrayTypeInfo(typeInfo).elType <> nil then
typeInfo := PDynArrayTypeInfo(typeInfo).elType^
else
typeInfo := nil;
neededSize := newLength*elSize;
if neededSize div newLength <> elSize then
Error(reRangeError);
Inc(neededSize, Sizeof(Longint)*2);
// If the heap object isn't shared (ref count = 1), just resize it. Otherwise, we make a copyif (p = nil) or (PLongint(p)^ = 1) then
begin
pp := p;
if (newLength < oldLength) and (typeInfo <> nil) then
FinalizeArray(PChar(p) + Sizeof(Longint)*2 + newLength*elSize, typeInfo, oldLength - newLength);
ReallocMem(pp, neededSize);
p := pp;
end
else
begin
Dec(PLongint(p)^);
GetMem(p, neededSize);
minLength := oldLength;
if minLength > newLength then
minLength := newLength;
if typeInfo <> nil then
begin
FillChar((PChar(p) + Sizeof(Longint)*2)^, minLength*elSize, 0);
CopyArray(PChar(p) + Sizeof(Longint)*2, a, typeInfo, minLength)
end
else
Move(PChar(a)^, (PChar(p) + Sizeof(Longint)*2)^, minLength*elSize);
end;
// The heap object will now have a ref count of 1 and the new length
PLongint(p)^ := 1;
Inc(PLongint(p));
PLongint(p)^ := newLength;
Inc(PLongint(p));
// Set the new memory to all zero bits
FillChar((PChar(p) + elSize * oldLength)^, elSize * (newLength - oldLength), 0);
// Take care of the inner dimensions, if anyif dimCnt > 1 then
begin
Inc(lengthVec);
Dec(dimCnt);
for i := 0 to newLength-1 do
DynArraySetLength(PPointerArray(p)[i], typeInfo, dimCnt, lengthVec);
end;
a := p;
end;
function SysReallocMem(p: Pointer; size: Integer): Pointer;
// Resize memory block.var
n: Pointer; oldSize: Integer;
begin
if not initialized and not InitAllocator then begin
result := nil;
exit;
end;
try
if IsMultiThread then EnterCriticalSection(heapLock);
if ResizeInPlace(p, size) then
result := p
else begin
n := SysGetMem(size);
oldSize := (PUsed(PChar(p)-sizeof(PUsed)).sizeFlags and not cFlags) - sizeof(TUsed);
if oldSize > size then
oldSize := size;
if n <> nil then begin
Move(p^, n^, oldSize);
SysFreeMem(p);
end;
result := n;
end;
finally
if IsMultiThread then LeaveCriticalSection(heapLock);
end;
end;
function ResizeInPlace(p: Pointer; newSize: Integer): Boolean;
var u, n: PUsed; f: PFree; oldSize, blkSize, neededSize: Integer;
begin
Inc(newSize, sizeof(TUsed)+cAlign-1);
newSize := newSize and not (cAlign-1);
if newSize < sizeof(TFree) then
newSize := sizeof(TFree);
u := PUsed(PChar(p) - sizeof(TUsed));
oldSize := u.sizeFlags and not cFlags;
n := PUsed( PChar(u) + oldSize );
if newSize = oldSize then
begin
Result := True;
Exit;
end;
if newSize < oldSize then begin
blkSize := oldSize - newSize;
if PChar(n) = curAlloc then begin
Dec(curAlloc, blkSize);
Inc(remBytes, blkSize);
if remBytes < sizeof(TFree) then begin
Inc(curAlloc, blkSize);
Dec(remBytes, blkSize);
newSize := oldSize;
end;
end else begin
n := PUsed(PChar(u) + oldSize);
if n.sizeFlags and cThisUsedFlag = 0 then begin
f := PFree(n);
Inc(blkSize, f.size);
DeleteFree(f);
end;
if blkSize >= sizeof(TFree) then begin
n := PUsed(PChar(u) + newSize);
n.sizeFlags := blkSize or cThisUsedFlag;
InternalFreeMem(PChar(n) + sizeof(TUsed));
end else
newSize := oldSize;
end;
end else begin
repeat
neededSize := newSize - oldSize;
if PChar(n) = curAlloc then begin
if remBytes >= neededSize then begin
Dec(remBytes, neededSize);
Inc(curAlloc, neededSize);
if remBytes < sizeof(TFree) then begin
Inc(curAlloc, remBytes);
Inc(newSize, remBytes);
remBytes := 0;
end;
Inc(AllocMemSize, newSize - oldSize);
u.sizeFlags := newSize or u.sizeFlags and cFlags;
result := true;
exit;
end else begin
FreeCurAlloc;
n := PUsed( PChar(u) + oldSize );
end;
end;
if n.sizeFlags and cThisUsedFlag = 0 then begin
f := PFree(n);
blkSize := f.size;
if blkSize < neededSize then begin
n := PUsed(PChar(n) + blkSize);
Dec(neededSize, blkSize);
end else begin
DeleteFree(f);
Dec(blkSize, neededSize);
if blkSize >= sizeof(TFree) then
InsertFree(PChar(u) + newSize, blkSize)
else begin
Inc(newSize, blkSize);
n := PUsed(PChar(u) + newSize);
n.sizeFlags := n.sizeFlags and not cPrevFreeFlag;
end;
break;
end;
end;
if n.sizeFlags and cFillerFlag <> 0 then begin
n := PUsed(PChar(n) + n.sizeFlags and not cFlags);
if NewCommitAt(n, neededSize) then begin
n := PUsed( PChar(u) + oldSize );
continue;
end;
end;
result := False;
exit;
until False;
end;
Inc(AllocMemSize, newSize - oldSize);
u.sizeFlags := newSize or u.sizeFlags and cFlags;
result := True;
end;
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
и солнце б утром не вставало, когда бы не было меня
Re[4]: Динамический массив в C#
От:
Аноним
Дата:
21.02.05 17:37
Оценка:
> — Уволить его и нанять того, кто работает лучше. (Varg)
Ничего подобного я не говорил.
> При создании нового массива ты создаешь новый массив, а старый массив остается прежнего размера. А то что ты ссылку на новый массив сохраняешь в ссылке на старый погоды не делает. Подумай о том, что кто-то может все еще ссылаться на старый массив и твое якобы "изменение" массива его никак не коснется.
int[] ptr;
int[] arr = new int[] { 1 };
ptr = arr;
ptr[0] = 2; // тоже самое, что и arr[0] = 2;
Increase(ref arr, 1); // arr — это ссылка на новый массив
arr[1] = 3; // меняет значение в новом массиве
ptr[0] = 4; // меняет значение в старом массиве
Чтобы такого не было, просто делается обертка.
public class DinArr<T>
{
public DinArr(int size)
{
_Array = new T[size];
}
private T[] _Array;
public void Increase(int delta)
{
T[] tmp = new T[_Array.Length + delta];
Array.Copy(_Array, 0, tmp, 0, _Array.Length);
_Array = tmp;
}
public T this[int i]
{
get { return _Array; }
set
{
_Array[i] = value;
}
}
}
И теперь после вызова arr.Increase(1); к элементам массива можно обращаться как через arr так и ptr.
Здравствуйте, Аноним, Вы писали:
А>> При создании нового массива ты создаешь новый массив, а старый массив остается прежнего размера. А то что ты ссылку на новый массив сохраняешь в ссылке на старый погоды не делает. Подумай о том, что кто-то может все еще ссылаться на старый массив и твое якобы "изменение" массива его никак не коснется. А> А>int[] ptr; А>int[] arr = new int[] { 1 }; А>ptr = arr; А>ptr[0] = 2; // тоже самое, что и arr[0] = 2; А>Increase(ref arr, 1); // arr — это ссылка на новый массив А>arr[1] = 3; // меняет значение в новом массиве А>ptr[0] = 4; // меняет значение в старом массиве А> А>Чтобы такого не было, просто делается обертка.
Это как-то противоречит тому, что я сказал про "динамичность" размера массивов? Да и зачем так изголяться, если есть ArrayList который реализует все то же самое, но эффективней.
Re[4]: Динамический массив в C#
От:
Аноним
Дата:
22.02.05 12:16
Оценка:
Lloyd
Замечательно. Сначала ты приписываешь мне какие-то мысли, а потом пытаешься доказать мне, что они неправильные .
Ладно, не будем захламлять топик бессмысленным флеймом — всё-равно каждый останется при своём мнении.