source: trunk/ab5.0/ablib/src/Classes/System/Collections/Generic/List.ab @ 633

Last change on this file since 633 was 633, checked in by NoWest, 14 years ago

AsReadOnlyCollectionを実装するとうまくコンパイルできない問題ですが、
それ以前の問題として、Listクラス内でAdd()メソッドでIEnumeratorのCurrentプロパティの値を設定できないエラーがあります。

症状としてはCurrentの結果がT型であるのにListのAddはByte型とに認識され
TからByte型にキャストできないとエラーがでます。

File size: 6.8 KB
Line 
1
2Namespace System
3Namespace Collections
4Namespace Generic
5
6Namespace Detail
7    Class PointerEnumerator<T>
8        Implements IEnumerator<T>
9    Public
10        Sub PointerEnumerator(ptr As *T, count As Long)
11            p = ptr
12            n = count
13            cur = -1
14        End Sub
15
16        Function MoveNext() As Boolean
17            cur++
18            MoveNext = (cur <> n)
19        End Function
20
21        Sub Reset()
22            n = -1
23        End Sub
24
25        Function Current() As T
26            Current = p[cur]
27        End Function
28
29        Virtual Sub Dispose()
30            p = NULL
31            n = 0
32            cur = -1
33        End Sub
34    Private
35        p As *T
36        n As Long
37        cur As Long
38    End Class
39End Namespace
40
41Class List<T>
42    Implements IList<T>
43
44    items As *T
45    capacity As Long
46    count As Long
47
48    Sub Realloc( allocateSize As Long )
49        items = realloc( items, allocateSize * SizeOf(T) )
50        capacity = allocateSize
51    End Sub
52
53    Sub _Initialize( capacity As Long )
54        This.items = GC_malloc( capacity * SizeOf(T) )
55        This.capacity = capacity
56    End Sub
57
58    Sub SetLeastCapacity( capacity As Long )
59        If This.capacity < capacity Then
60            Realloc(capacity)
61        End If
62    End Sub
63Public
64    Sub List()
65        _Initialize(16)
66    End Sub
67
68    /*!
69    @brief  予め要素数を指定してList<T>を初期化
70    @author NoWest
71    @date   2008/07/13
72    @param  リストの要素数
73    */
74    Sub List( capacity As Long )
75        _Initialize( capacity )
76    End Sub
77
78    /*!
79    @brief  既存の配列List<T>を初期化
80    @author NoWest
81    @date   2008/07/13
82    @param  基になる配列へのポインタ
83    @param  配列の長さ
84    */
85    Sub List( array As *T, length As Long )
86        _Initialize( length )
87
88        memmove( This.items, array, length * SizeOf(T) )
89        This.count = length
90    End Sub
91
92    /*!
93    @brief  既存のIEnumerator<T>を使用してListを初期化
94    @author NoWest
95    @date   2008/09/22
96    @param  基になるIEnumerator<T>
97    */
98    Sub List ( enumerator As IEnumerator<T> )
99        _Initialize( 1 )
100        While enumerator.MoveNext()
101            'ここでTをByetに変換できないというエラーになる This.Add(enumerator.Current())
102        Wend
103    End Sub
104
105    /*!
106    @brief  インデクサ
107    @author Daisuke Yamamoto
108    @date   2007/08/22
109    @param  インデックス
110    */
111    Sub Operator[] ( index As Long, item As T )
112        Item[index] = item
113    End Sub
114    Function Operator[] ( index As Long ) As T
115        Return Item[index]
116    End Function
117
118    /*!
119    @brief  インデクサ
120    @author Egtra
121    @date   2008/08/04
122    @param  インデックス
123    */
124    Override Sub Item( index As Long, item As T )
125        If 0 <= index And index < capacity Then
126            items[index]=item
127        Else
128            Throw New ArgumentOutOfRangeException("index")
129        End If
130    End Sub
131    Override Function Item( index As Long ) As T
132        If 0 <= index And index < capacity Then
133            Return items[index]
134        Else
135            Throw New ArgumentOutOfRangeException("index")
136        End If
137    End Function
138    /*!
139    @brief  ポインタ型へのキャスト
140    @author Daisuke Yamamoto
141    @date   2007/08/22
142    @param  インデックス
143    */
144    Function Operator() As *T
145        Return items
146    End Function
147
148
149    '----------------------------------------------------------------
150    ' パブリック プロパティ
151    '----------------------------------------------------------------
152
153    /*!
154    @brief  Listに格納されている要素の数を取得する
155    @author Daisuke Yamamoto
156    @date   2007/08/22
157    */
158    Override Function Count() As Long
159        Return This.count
160    End Function
161
162    Const Function Capacity() As Long
163        Return This.capacity
164    End Function
165
166    Sub Capacity(c As Long)
167        If c <> capacity Then
168            If c < capacity Then
169                Throw New ArgumentOutOfRangeException("capacity")
170            Else
171                Realloc(c)
172            End If
173        End If
174    End Sub
175   
176    /*!
177    @brief  Listが読み込み専用かどうかを取得する
178    @author NoWest
179    @date   2008/07/12
180    */
181    Override Function IsReadOnly() As Boolean
182        Return False
183    End Function
184
185    '----------------------------------------------------------------
186    ' パブリック メソッド
187    '----------------------------------------------------------------
188
189    /*!
190    @brief  Listの末端に要素を追加する
191    @author Daisuke Yamamoto
192    @date   2007/08/22
193    @param  追加するオブジェクト
194    */
195    Override Sub Add( item As T )
196        SetLeastCapacity(This.count + 1)
197        This.items[ This.count ] = item
198        This.count++
199    End Sub
200
201    /*!
202    @brief  読み取り専用のListのラッパーを取得
203    @author NoWest
204    @date   2008/09/22
205    */
206/*  Function AsReadOnly() As System.Collections.ObjectModel.ReadOnlyCollection<T>
207        Return New System.Collections.ObjectModel.ReadOnlyCollection<T>(This)
208    End Function*/
209
210    /*!
211    @brief  Listからすべての要素を削除する
212    @author Daisuke Yamamoto
213    @date   2007/08/22
214    */
215    Override Sub Clear()
216        This.count = 0
217    End Sub
218
219/*  Override Function Contains ( item As T ) As Boolean
220        TODO
221    End Function*/
222
223    /*!
224    @brief  List内から、最初に出現する値のインデックスを取得する
225    @author Daisuke Yamamoto
226    @date   2007/08/22
227    @return インデックス(見つからなかったときは-1)
228    */
229    Override Function IndexOf( item As T ) As Long
230        Dim i As Long
231        For i = 0 To ELM( This.count )
232            If items[i].Equals(item) Then
233                Return i
234            End If
235        Next
236        Return -1
237    End Function
238
239    /*!
240    @brief  List内の指定したインデックスの位置に要素を挿入する
241    @author Daisuke Yamamoto
242    @date   2007/08/22
243    */
244    Override Sub Insert( index As Long, item As T )
245        SetLeastCapacity(This.count + 1)
246        memmove( items + (index+1)*SizeOf(T), items + index*SizeOf(T), (This.count - index)*SizeOf(T) )
247        items[index] = item
248        This.count++
249    End Sub
250
251    /*!
252    @brief  List内で最初に出現する値を削除する
253    @author Daisuke Yamamoto
254    @date   2007/09/28
255    @return 値が削除されたときはTrue、されなかったときはFlaseが返る
256    */
257    Override Function Remove( item As T ) As Boolean
258        Dim index = IndexOf( item )
259        If index = -1 Then
260            Return False
261        End If
262
263        removeAtImpl( index )
264        Return True
265    End Function
266
267    /*!
268    @brief  List内の指定したインデックスの要素を削除する
269    @author Daisuke Yamamoto
270    @date   2007/10/03
271    */
272    Override Sub RemoveAt( index As Long )
273        If 0 <= index And index < capacity Then
274            removeAtImpl( index )
275        Else
276            Throw New ArgumentOutOfRangeException("index")
277        End If
278    End Sub
279Private
280    Sub removeAtImpl( index As Long )
281        memmove( items + index*SizeOf(T), items + (index+1)*SizeOf(T), (This.count - (index+1))*SizeOf(T) )
282        This.count--
283    End Sub
284
285Public
286
287    /*!
288    @brief  Listの要素を文字列で返す
289    @author OverTaker
290    @date   2008/6/26
291    @return 文字列
292    */
293    Override Function ToString() As String
294        Dim string = New Text.StringBuilder
295        Dim i As Long
296        For i = 0 To ELM( This.count )
297            string.Append(This[i]).Append(Ex"\r\n")
298        Next
299        Return string.ToString
300    End Function
301
302    /*!
303    @brief  実際の要素数が現在の容量の 90% 未満の場合は、容量をその数に設定します
304    @author NoWest
305    @date   2008/07/20
306    */
307    Sub TrimExcess ()
308        If ( This.capacity ) * 0.9 > This.count Then
309            Realloc( This.count )
310        End If
311    End Sub
312
313    /*!
314    @brief  IEnumeratorインターフェイスを取得する
315    @author Daisuke Yamamoto
316    @date   2007/11/19
317    @return IEnumeratorインターフェイスが返る
318    */
319    Override Function GetEnumerator() As IEnumerator<T>
320        Return New Detail.PointerEnumerator<T>(items, count)
321    End Function
322End Class
323
324
325End Namespace
326End Namespace
327End Namespace
Note: See TracBrowser for help on using the repository browser.