Задача: Обертки для массивов
Исходник: Обертка, wrapper для массива с функциями кеширования, реализованная через связные списки, язык: C# [code #174, hits: 7994]
автор: - [добавлен: 15.09.2006]
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Runtime.InteropServices;
  5. using System.ComponentModel;
  6. using System.Reflection;
  7.  
  8. public interface ITypedArray<T> : IEnumerable<T>
  9. {
  10. int Length { get;}
  11. int Rank { get;}
  12. object SyncRoot { get;}
  13. bool IsFixedSize { get;}
  14. bool IsReadOnly { get;}
  15. bool IsSynchronized { get;}
  16. void CopyTo(ITypedArray<T> array, int index);
  17. bool Exists(T value);
  18. T Find(Predicate<T> predicate);
  19. void ForEach(Action<T> action);
  20. int GetLowerBound(int dimension);
  21. int GetUpperBound(int dimension);
  22. T GetValue(int index, params int[] indexes);
  23. void SetValue(T value, int index, params int[] indexes);
  24. int IndexOf(T value);
  25. void Initialize();
  26. int GetLength(int dimension);
  27. ITypedArray<T> Reverse();
  28. T[] ToSingleArray();
  29. }
  30.  
  31. internal class CachedArrayItem<T>
  32. {
  33. public CachedArrayItem(int index, ArrayItem<T> arrayItem)
  34. {
  35. Index = index;
  36. Item = arrayItem;
  37. }
  38. public CachedArrayItem()
  39. : this(-1, null)
  40. {
  41. }
  42. public int Index;
  43. public ArrayItem<T> Item;
  44. }
  45.  
  46. public class ArrayItem<T>
  47. {
  48. public ArrayItem(T data, ArrayItem<T> nextItem)
  49. {
  50. Data = data;
  51. NextItem = nextItem;
  52. }
  53. public ArrayItem()
  54. : this(default(T), null)
  55. {
  56. }
  57. public T Data;
  58. public ArrayItem<T> NextItem;
  59. }
  60.  
  61. internal class ArrayEnumerator<T> : IEnumerator<T>, IDisposable
  62. {
  63. protected readonly ArrayItem<T> m_firstItem;
  64. private ArrayItem<T> m_current;
  65. public bool IsInitialized;
  66. public ArrayEnumerator(ArrayItem<T> firstItem)
  67. {
  68. m_firstItem = firstItem;
  69. Reset();
  70. }
  71. public void Reset()
  72. {
  73. m_current = new ArrayItem<T>(default(T), m_firstItem);
  74. IsInitialized = false;
  75. }
  76. public bool MoveNext()
  77. {
  78. IsInitialized = true;
  79. m_current = m_current.NextItem;
  80. if (m_current == null) return false;
  81. return true;
  82. }
  83. public T Current
  84. {
  85. get
  86. {
  87. if (!IsInitialized) throw new InvalidOperationException("Enumeration has not started. Call MoveNext");
  88. return m_current.Data;
  89. }
  90. }
  91. object System.Collections.IEnumerator.Current
  92. {
  93. get
  94. {
  95. if (!IsInitialized) throw new InvalidOperationException("Enumeration has not started. Call MoveNext");
  96. return m_current;
  97. }
  98. }
  99. public void Dispose()
  100. {
  101. m_current = null;
  102. }
  103. }
  104.  
  105.  
  106. public class CachedSingleArray<T> : SingleArray<T>
  107. {
  108. private readonly CachedArrayItem<T> cache;
  109. public CachedSingleArray(int length)
  110. :base(length)
  111. {
  112. cache = new CachedArrayItem<T>(0, firstItem);
  113. }
  114.  
  115. public CachedSingleArray(T[] innerArray)
  116. :base(innerArray)
  117. {
  118. cache = new CachedArrayItem<T>(0, firstItem);
  119. }
  120.  
  121. #region SingleArray<T> members
  122. public override T GetValue(int index, params int[] indexes)
  123. {
  124. if (indexes.Length != 0) throw new ArgumentException("Current array is one-dimensional");
  125. ArrayItem<T> currentItem = null;
  126. int startIndex = 0;
  127. if (index >= cache.Index)
  128. {
  129. currentItem = new ArrayItem<T>(default(T), cache.Item);
  130. startIndex = cache.Index;
  131. }
  132. else
  133. currentItem = new ArrayItem<T>(default(T), firstItem);
  134. for (int i = startIndex; i <= index; i++)
  135. {
  136. currentItem = currentItem.NextItem;
  137. if (currentItem == null) throw new IndexOutOfRangeException("Index of array element out of range");
  138. }
  139. cache.Index = index;
  140. return (cache.Item = currentItem).Data;
  141. }
  142. public override void SetValue(T value, int index, params int[] indexes)
  143. {
  144. if (indexes.Length != 0) throw new ArgumentException("Current array is one-dimensional");
  145. ArrayItem<T> currentItem = null;
  146. int startIndex = 0;
  147. if (index >= cache.Index)
  148. {
  149. currentItem = new ArrayItem<T>(default(T), cache.Item);
  150. startIndex = cache.Index;
  151. }
  152. else
  153. currentItem = new ArrayItem<T>(default(T), firstItem);
  154. for (int i = startIndex; i <= index; i++)
  155. {
  156. currentItem = currentItem.NextItem;
  157. if (currentItem == null) throw new IndexOutOfRangeException("Index of array element out of range");
  158. }
  159. cache.Index = index;
  160. (cache.Item = currentItem).Data = value;
  161. }
  162. #endregion
  163. }
  164.  
  165. public class SingleArray<T> : ITypedArray<T>, ICloneable
  166. {
  167. private int m_length;
  168. protected ArrayItem<T> firstItem;
  169. public SingleArray(int length)
  170. {
  171. m_length = length;
  172. firstItem = null;
  173. if (length > 0)
  174. {
  175. ArrayItem<T> tempItem = firstItem = new ArrayItem<T>();
  176. for (int i = 1; i < length; i++)
  177. {
  178. tempItem = tempItem.NextItem = new ArrayItem<T>();
  179. }
  180. tempItem.NextItem = null;
  181. }
  182. }
  183. public SingleArray(T[] innerArray)
  184. {
  185. m_length = innerArray.Length;
  186. ArrayItem<T> arrayItem = firstItem = new ArrayItem<T>();
  187. arrayItem.Data = innerArray[0];
  188. for (int i = 1; i < m_length; i++)
  189. {
  190. arrayItem = arrayItem.NextItem = new ArrayItem<T>();
  191. arrayItem.Data = innerArray[i];
  192. }
  193. arrayItem.NextItem = null;
  194. }
  195. public T this[int index]
  196. {
  197. get
  198. {
  199. return GetValue(index);
  200. }
  201. set
  202. {
  203. SetValue(value, index);
  204. }
  205. }
  206. public virtual int GetLowerBound()
  207. {
  208. return 0;
  209. }
  210. public virtual int GetUpperBound()
  211. {
  212. return m_length - 1;
  213. }
  214. #region ITypedArray<T> members
  215. public int Length
  216. {
  217. get { return m_length; }
  218. }
  219. public int Rank
  220. {
  221. get { return 1; }
  222. }
  223. public object SyncRoot
  224. {
  225. get { return firstItem; }
  226. }
  227. public bool IsFixedSize
  228. {
  229. get { return true; }
  230. }
  231. public bool IsReadOnly
  232. {
  233. get { return true; }
  234. }
  235. public bool IsSynchronized
  236. {
  237. get { return false; }
  238. }
  239. public void CopyTo(ITypedArray<T> sourceArray, int index)
  240. {
  241. ArrayItem<T> current = firstItem;
  242. int counter = index;
  243. do
  244. {
  245. sourceArray.SetValue(current.Data, counter++);
  246. current = current.NextItem;
  247. } while (current != null && counter < sourceArray.Length);
  248. }
  249. public bool Exists(T value)
  250. {
  251. return IndexOf(value) != -1;
  252. }
  253. public int IndexOf(T value)
  254. {
  255. ArrayItem<T> current = firstItem;
  256. int counter = 0;
  257. do
  258. {
  259. if (current.Data.Equals(value)) return counter;
  260. counter++;
  261. current = current.NextItem;
  262. } while (current != null);
  263. return -1;
  264. }
  265. public virtual T GetValue(int index, params int[] indexes)
  266. {
  267. if (indexes.Length != 0) throw new ArgumentException("Current array is one-dimensional");
  268. ArrayItem<T> currentItem = new ArrayItem<T>(default(T), firstItem);
  269. for (int i = 0; i <= index; i++)
  270. {
  271. currentItem = currentItem.NextItem;
  272. if (currentItem == null) throw new IndexOutOfRangeException("Index of array element out of range");
  273. }
  274. return currentItem.Data;
  275. }
  276. public virtual void SetValue(T value, int index, params int[] indexes)
  277. {
  278. if (indexes.Length != 0) throw new ArgumentException("Current array is one-dimensional");
  279. ArrayItem<T> currentItem = new ArrayItem<T>(default(T), firstItem);
  280. for (int i = 0; i <= index; i++)
  281. {
  282. currentItem = currentItem.NextItem;
  283. if (currentItem == null) throw new IndexOutOfRangeException("Index of array element out of range");
  284. }
  285. currentItem.Data = value;
  286. }
  287. public T Find(Predicate<T> predicate)
  288. {
  289. ArrayItem<T> current = firstItem;
  290. do
  291. {
  292. if (predicate(current.Data)) return current.Data;
  293. current = current.NextItem;
  294. } while (current != null);
  295. return default(T);
  296. }
  297. public void ForEach(Action<T> action)
  298. {
  299. ArrayItem<T> current = firstItem;
  300. do
  301. {
  302. action(current.Data);
  303. current = current.NextItem;
  304. } while (current != null);
  305. }
  306. public int GetLowerBound(int dimension)
  307. {
  308. if (dimension != 0) throw new ArgumentException("Current array is one-dimensional");
  309. return GetLowerBound();
  310. }
  311. public int GetUpperBound(int dimension)
  312. {
  313. if (dimension != 0) throw new ArgumentException("Current array is one-dimensional");
  314. return GetUpperBound();
  315. }
  316. public int GetLength(int dimension)
  317. {
  318. if (dimension != 0) throw new ArgumentException("Current array is one-dimensional");
  319. return m_length;
  320. }
  321. public void Initialize()
  322. {
  323. Initialize(default(T));
  324. }
  325. public ITypedArray<T> Reverse()
  326. {
  327. T[] buffer = ToSingleArray(false);
  328. Array.Reverse(buffer);
  329. return new SingleArray<T>(buffer);
  330. }
  331. public T[] ToSingleArray()
  332. {
  333. return ToSingleArray(false);
  334. }
  335. #endregion
  336. #region IEnumerable<T> members
  337. public IEnumerator<T> GetEnumerator()
  338. {
  339. return new ArrayEnumerator<T>(firstItem);
  340. }
  341. System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
  342. {
  343. return new ArrayEnumerator<T>(firstItem);
  344. }
  345. #endregion
  346. #region ICloneable members
  347. public object Clone()
  348. {
  349. return MemberwiseClone();
  350. }
  351. #endregion
  352. public void Initialize(T value)
  353. {
  354. ArrayItem<T> current = firstItem;
  355. do
  356. {
  357. current.Data = value;
  358. current = current.NextItem;
  359. } while (current != null);
  360. }
  361. public T[] ToSingleArray(bool isCopy)
  362. {
  363. T[] buffer = null;
  364. SingleArray<T> singleArray = null;
  365. if (isCopy) singleArray = (SingleArray<T>)Clone();
  366. else singleArray = this;
  367. ArrayItem<T> current = singleArray.firstItem;
  368. int counter = 0;
  369. do
  370. {
  371. buffer[counter++] = current.Data;
  372. current = current.NextItem;
  373. } while (current != null);
  374. return buffer;
  375. }
  376. public static T[] Concat(T[] self, params T[][] arrays)
  377. {
  378. List<T> result = new List<T>(self);
  379. foreach (T[] array in arrays)
  380. {
  381. result.AddRange(array);
  382. }
  383. return result.ToArray();
  384. }
  385. public static explicit operator SingleArray<T>(T[] innerArray)
  386. {
  387. return new SingleArray<T>(innerArray);
  388. }
  389. public static implicit operator T[](SingleArray<T> innerArray)
  390. {
  391. return innerArray.ToSingleArray(false);
  392. }
  393. }
  394.  
  395. public class TypedArray<T> : ICloneable, ITypedArray<T>
  396. {
  397. private readonly CachedSingleArray<int> indicies;
  398.  
  399. protected readonly ArrayItem<T> firstItem;
  400.  
  401. #region ITypedArray<T> members
  402. public virtual bool IsFixedSize
  403. {
  404. get { return true; }
  405. }
  406. public virtual bool IsReadOnly
  407. {
  408. get { return true; }
  409. }
  410. public virtual bool IsSynchronized
  411. {
  412. get { return false; }
  413. }
  414. public virtual int Length
  415. {
  416. get
  417. {
  418. ArrayItem<T> current = firstItem;
  419. int result = 0;
  420. while (current != null)
  421. {
  422. result++;
  423. current = current.NextItem;
  424. }
  425. return result;
  426. }
  427. }
  428. public Object SyncRoot
  429. {
  430. get
  431. {
  432. return firstItem;
  433. }
  434. }
  435. public int Rank
  436. {
  437. get { return indicies.Length; }
  438. }
  439. public void CopyTo(ITypedArray<T> sourceArray, int index)
  440. {
  441. ArrayItem<T> current = firstItem;
  442. int counter = index;
  443. do
  444. {
  445. sourceArray.SetValue(current.Data, counter++);
  446. current = current.NextItem;
  447. } while (current != null && counter < sourceArray.Length);
  448. }
  449. public bool Exists(T value)
  450. {
  451. return IndexOf(value) != -1;
  452. }
  453. public T Find(Predicate<T> predicate)
  454. {
  455. ArrayItem<T> current = firstItem;
  456. do
  457. {
  458. if (predicate(current.Data)) return current.Data;
  459. current = current.NextItem;
  460. } while (current != null);
  461. return default(T);
  462. }
  463. public ITypedArray<T> Reverse()
  464. {
  465. T[] buffer = ToSingleArray(true);
  466. Array.Reverse(buffer);
  467. return new TypedArray<T>(buffer);
  468. }
  469. public virtual int GetUpperBound(int dimension)
  470. {
  471. return GetLength(dimension) - 1;
  472. }
  473. public virtual int GetLowerBound(int dimension)
  474. {
  475. return 0;
  476. }
  477. public int IndexOf(T value)
  478. {
  479. ArrayItem<T> current = firstItem;
  480. int counter = 0;
  481. do
  482. {
  483. if (current.Data.Equals(value)) return counter;
  484. counter++;
  485. current = current.NextItem;
  486. } while (current != null);
  487. return -1;
  488. }
  489. public void SetValue(T value, int index, params int[] indexes)
  490. {
  491. this[index, indexes] = value;
  492. }
  493. public T GetValue(int index, params int[] indexes)
  494. {
  495. return this[index, indexes];
  496. }
  497. public void Initialize()
  498. {
  499. Initialize(default(T));
  500. }
  501. public int GetLength(int dimension)
  502. {
  503. return indicies[dimension];
  504. }
  505. public void ForEach(Action<T> action)
  506. {
  507. ArrayItem<T> current = firstItem;
  508. do
  509. {
  510. action(current.Data);
  511. current = current.NextItem;
  512. } while (current != null);
  513. }
  514. public T[] ToSingleArray()
  515. {
  516. return ToSingleArray(false);
  517. }
  518. #endregion
  519.  
  520. #region IEnumerable<T> members
  521. public IEnumerator<T> GetEnumerator()
  522. {
  523. return new ArrayEnumerator<T>(firstItem);
  524. }
  525.  
  526. System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
  527. {
  528. return new ArrayEnumerator<T>(firstItem);
  529. }
  530. #endregion
  531.  
  532. public virtual long LongLength
  533. {
  534. get
  535. {
  536. ArrayItem<T> current = firstItem;
  537. long result = 0;
  538. while (current != null)
  539. {
  540. result++;
  541. current = current.NextItem;
  542. }
  543. return result;
  544. }
  545. }
  546.  
  547. public T[] ToSingleArray(bool isCopy)
  548. {
  549. T[] buffer = null;
  550. TypedArray<T> singleArray = null;
  551. if (isCopy) singleArray = (TypedArray<T>)Clone();
  552. else singleArray = this;
  553. ArrayItem<T> current = singleArray.firstItem;
  554. int counter = 0;
  555. do
  556. {
  557. buffer[counter++] = current.Data;
  558. current = current.NextItem;
  559. } while (current != null);
  560. return buffer;
  561. }
  562.  
  563. public static implicit operator T[](TypedArray<T> typedArray)
  564. {
  565. return typedArray.ToSingleArray(false);
  566. }
  567.  
  568. public static explicit operator TypedArray<T>(T[] managedArray)
  569. {
  570. return new TypedArray<T>(managedArray);
  571. }
  572.  
  573. public TypedArray(int size, params int[] sizes)
  574. {
  575. indicies = new CachedSingleArray<int>(SingleArray<int>.Concat(new int[] { size }, sizes));
  576. foreach (int dimSize in sizes)
  577. size *= dimSize;
  578. firstItem = null;
  579. if (size > 0)
  580. {
  581. ArrayItem<T> tempItem = firstItem = new ArrayItem<T>();
  582. for (int i = 1; i < size; i++)
  583. {
  584. tempItem = tempItem.NextItem = new ArrayItem<T>();
  585. }
  586. tempItem.NextItem = null;
  587. }
  588. }
  589.  
  590. public T this[int index, params int[] indexes]
  591. {
  592. get
  593. {
  594. return GetValueDirectly(GetAbsoluteIndex(index, indexes));
  595. }
  596. set
  597. {
  598. SetValueDirectly(value, GetAbsoluteIndex(index, indexes));
  599. }
  600. }
  601.  
  602. public TypedArray(T[] array) //Create alias array
  603. {
  604. //array = (T[])array.Clone(); //Create shallow copy
  605. indicies = new CachedSingleArray<int>(1);
  606. indicies[0] = array.Length;
  607. ArrayItem<T> tempItem = firstItem = new ArrayItem<T>();
  608. tempItem.Data = array[0];
  609. for (int i = 1; i < array.Length; i++)
  610. {
  611. tempItem = tempItem.NextItem = new ArrayItem<T>(array[i], null);
  612. }
  613. }
  614.  
  615.  
  616. public virtual void SetValueDirectly(T value, int absoluteIndex)
  617. {
  618. ArrayItem<T> currentItem = new ArrayItem<T>(default(T), firstItem);
  619. for (int i = 0; i <= absoluteIndex; i++)
  620. {
  621. currentItem = currentItem.NextItem;
  622. if (currentItem == null) throw new IndexOutOfRangeException("Index of array element out of range");
  623. }
  624. currentItem.Data = value;
  625. }
  626.  
  627. public virtual T GetValueDirectly(int absoluteIndex)
  628. {
  629. ArrayItem<T> currentItem = new ArrayItem<T>(default(T), firstItem);
  630. for (int i = 0; i <= absoluteIndex; i++)
  631. {
  632. currentItem = currentItem.NextItem;
  633. if (currentItem == null) throw new IndexOutOfRangeException("Index of array element out of range");
  634. }
  635. return currentItem.Data;
  636. }
  637.  
  638. public void SetValueDirectly(T value, long absoluteLongIndex)
  639. {
  640. ArrayItem<T> currentItem = new ArrayItem<T>(default(T), firstItem);
  641. for (long i = 0; i <= absoluteLongIndex; i++)
  642. {
  643. currentItem = currentItem.NextItem;
  644. if (currentItem == null) throw new IndexOutOfRangeException("Index of array element out of range");
  645. }
  646. currentItem.Data = value;
  647. }
  648.  
  649. public T GetValueDirectly(long absoluteLongIndex)
  650. {
  651. ArrayItem<T> currentItem = new ArrayItem<T>(default(T), firstItem);
  652. for (long i = 0; i <= absoluteLongIndex; i++)
  653. {
  654. currentItem = currentItem.NextItem;
  655. if (currentItem == null) throw new IndexOutOfRangeException("Index of array element out of range");
  656. }
  657. return currentItem.Data;
  658. }
  659.  
  660. public void Initialize(T value)
  661. {
  662. ArrayItem<T> current = firstItem;
  663. do
  664. {
  665. current.Data = value;
  666. current = current.NextItem;
  667. } while (current != null);
  668. }
  669.  
  670. public void Initialize(T[] initValue)
  671. {
  672. ArrayItem<T> current = firstItem;
  673. int counter = 0;
  674. do
  675. {
  676. current.Data = initValue[counter++];
  677. current = current.NextItem;
  678. } while (current != null && counter < initValue.Length);
  679. }
  680.  
  681. public static TypedArray<T> CreateAliasArray(T[] aliasArray)
  682. {
  683. return new TypedArray<T>(aliasArray);
  684. }
  685.  
  686. public object Clone()
  687. {
  688. return this.MemberwiseClone();
  689. }
  690.  
  691. public void CopyTo(TypedArray<T> sourceArray, long index)
  692. {
  693. ArrayItem<T> current = firstItem;
  694. long counter = index;
  695. do
  696. {
  697. sourceArray.SetValueDirectly(current.Data, counter++);
  698. current = current.NextItem;
  699. } while (current != null && counter < sourceArray.LongLength);
  700. }
  701.  
  702.  
  703.  
  704. public long LongIndexOf(T value)
  705. {
  706. ArrayItem<T> current = firstItem;
  707. long counter = 0;
  708. do
  709. {
  710. if (current.Data.Equals(value)) return counter;
  711. counter++;
  712. current = current.NextItem;
  713. } while (current != null);
  714. return -1;
  715. }
  716.  
  717. public int GetAbsoluteIndex(int index, params int[] indexes)
  718. {
  719. if (indexes.Length != indicies.Length - 1)
  720. throw new ArgumentException("The number of dimensions in the current array is not equal to the number of elements in indices");
  721. for (int i = 0; i < indexes.Length; i++)
  722. {
  723. if (indexes[i] >= indicies[i]) throw new IndexOutOfRangeException("Index of array element out of range");
  724. index += indexes[i] * indicies[i];
  725. }
  726. return index;
  727. }
  728.  
  729. public int[] GetDimensionIndexes(int absoluteIndex)
  730. {
  731. int[] result = new int[indicies.Length];
  732. int length = Length;
  733. for (int i = result.Length - 1; i >=0 ; i--)
  734. {
  735. length /= indicies[i];
  736. int temp = absoluteIndex / length;
  737. absoluteIndex -= temp * length;
  738. result[i] = temp;
  739. }
  740. return result;
  741. }
  742. }
  743.  
  744. public class CachedTypedArray<T> : TypedArray<T>
  745. {
  746. private readonly CachedArrayItem<T> cache;
  747. public CachedTypedArray(int size, params int[] sizes)
  748. :base(size, sizes)
  749. {
  750. cache = new CachedArrayItem<T>(0, firstItem);
  751. }
  752.  
  753. public CachedTypedArray(T[] innerArray)
  754. : base(innerArray)
  755. {
  756. cache = new CachedArrayItem<T>(0, firstItem);
  757. }
  758.  
  759. public override T GetValueDirectly(int absoluteIndex)
  760. {
  761. ArrayItem<T> currentItem = null;
  762. int startIndex = 0;
  763. if (absoluteIndex >= cache.Index)
  764. {
  765. currentItem = new ArrayItem<T>(default(T), cache.Item); //cache hit
  766. startIndex = cache.Index;
  767. }
  768. else
  769. currentItem = new ArrayItem<T>(default(T), firstItem); //cache missing
  770. for (int i = startIndex; i <= absoluteIndex; i++)
  771. {
  772. currentItem = currentItem.NextItem;
  773. if (currentItem == null) throw new IndexOutOfRangeException("Index of array element out of range");
  774. }
  775. cache.Index = absoluteIndex;
  776. return (cache.Item = currentItem).Data;
  777. }
  778.  
  779. public override void SetValueDirectly(T value, int absoluteIndex)
  780. {
  781. ArrayItem<T> currentItem = null;
  782. int startIndex = 0;
  783. if (absoluteIndex >= cache.Index)
  784. {
  785. currentItem = new ArrayItem<T>(default(T), cache.Item); //cache hit
  786. startIndex = cache.Index;
  787. }
  788. else
  789. currentItem = new ArrayItem<T>(default(T), firstItem); //cache missing
  790. for (int i = startIndex; i <= absoluteIndex; i++)
  791. {
  792. currentItem = currentItem.NextItem;
  793. if (currentItem == null) throw new IndexOutOfRangeException("Index of array element out of range");
  794. }
  795. cache.Index = absoluteIndex;
  796. (cache.Item = currentItem).Data = value;
  797. }
  798. }
Классы, реализующие работу с массивом без использования стандартных .NET-массивов и класса System.Array. Классы позволяют создавать многомерные массивы, используют простую технологию кэширования, что ускоряет поиск по массиву. Для реализации использовалась технология связанных списков.

Источник: http://sources.codenet.ru/download/1053/Arrays_cs.html
Тестировалось на: MS Visual Studio 2005, .NET Framework 2.0

+добавить реализацию