4
4
using System ;
5
5
using System . Collections ;
6
6
using System . Collections . Generic ;
7
+ using System . Runtime . CompilerServices ;
7
8
using Microsoft . Extensions . Internal ;
8
9
9
10
namespace Microsoft . Extensions . Primitives
@@ -16,19 +17,16 @@ public struct StringValues : IList<string>, IReadOnlyList<string>, IEquatable<St
16
17
private static readonly string [ ] EmptyArray = new string [ 0 ] ;
17
18
public static readonly StringValues Empty = new StringValues ( EmptyArray ) ;
18
19
19
- private readonly string _value ;
20
- private readonly string [ ] _values ;
20
+ private readonly object _value ;
21
21
22
22
public StringValues ( string value )
23
23
{
24
24
_value = value ;
25
- _values = null ;
26
25
}
27
26
28
27
public StringValues ( string [ ] values )
29
28
{
30
- _value = null ;
31
- _values = values ;
29
+ _value = values ;
32
30
}
33
31
34
32
public static implicit operator StringValues ( string value )
@@ -51,8 +49,11 @@ public static implicit operator string[] (StringValues value)
51
49
return value . GetArrayValue ( ) ;
52
50
}
53
51
54
- public int Count => _value != null ? 1 : ( _values ? . Length ?? 0 ) ;
52
+ public int Count => ( _value is string ) ? 1 : GetArrayCount ( ) ;
55
53
54
+ [ MethodImpl ( MethodImplOptions . NoInlining ) ]
55
+ private int GetArrayCount ( ) => ( ( _value as string [ ] ) ? . Length ?? 0 ) ;
56
+
56
57
bool ICollection < string > . IsReadOnly
57
58
{
58
59
get { return true ; }
@@ -68,49 +69,88 @@ public string this[int index]
68
69
{
69
70
get
70
71
{
71
- if ( _values != null )
72
- {
73
- return _values [ index ] ; // may throw
74
- }
75
- if ( index == 0 && _value != null )
72
+ if ( index == 0 )
76
73
{
77
- return _value ;
74
+ var stringVal = _value as string ;
75
+ if ( stringVal != null )
76
+ {
77
+ return stringVal ;
78
+ }
78
79
}
79
- return EmptyArray [ 0 ] ; // throws
80
+
81
+ return GetArrayItem ( index ) ;
80
82
}
81
83
}
82
84
85
+ [ MethodImpl ( MethodImplOptions . NoInlining ) ]
86
+ private string GetArrayItem ( int index )
87
+ {
88
+ var arrayValue = _value as string [ ] ;
89
+ if ( arrayValue != null )
90
+ {
91
+ return arrayValue [ index ] ; // may throw
92
+ }
93
+
94
+ return EmptyArray [ 0 ] ; // throws
95
+ }
96
+
83
97
public override string ToString ( )
84
98
{
85
99
return GetStringValue ( ) ?? string . Empty ;
86
100
}
87
101
88
102
private string GetStringValue ( )
89
103
{
90
- if ( _values == null )
104
+ var stringVal = _value as string ;
105
+ if ( stringVal != null )
91
106
{
92
- return _value ;
107
+ return stringVal ;
93
108
}
94
- switch ( _values . Length )
109
+
110
+ return GetArrayStringValue ( ) ;
111
+ }
112
+
113
+ [ MethodImpl ( MethodImplOptions . NoInlining ) ]
114
+ private string GetArrayStringValue ( )
115
+ {
116
+ var arrayValue = _value as string [ ] ;
117
+ if ( arrayValue != null )
95
118
{
96
- case 0 : return null ;
97
- case 1 : return _values [ 0 ] ;
98
- default : return string . Join ( "," , _values ) ;
119
+ switch ( arrayValue . Length )
120
+ {
121
+ case 0 : return null ;
122
+ case 1 : return arrayValue [ 0 ] ;
123
+ default : return string . Join ( "," , arrayValue ) ;
124
+ }
99
125
}
126
+ return null ;
100
127
}
101
-
128
+
102
129
public string [ ] ToArray ( )
103
130
{
104
131
return GetArrayValue ( ) ?? EmptyArray ;
105
132
}
106
133
107
134
private string [ ] GetArrayValue ( )
108
135
{
109
- if ( _value != null )
136
+ var arrayValue = _value as string [ ] ;
137
+ if ( arrayValue != null )
110
138
{
111
- return new [ ] { _value } ;
139
+ return arrayValue ;
112
140
}
113
- return _values ;
141
+
142
+ return GetStringArrayValue ( ) ;
143
+ }
144
+
145
+ [ MethodImpl ( MethodImplOptions . NoInlining ) ]
146
+ private string [ ] GetStringArrayValue ( )
147
+ {
148
+ var stringVal = _value as string ;
149
+ if ( stringVal != null )
150
+ {
151
+ return new [ ] { stringVal } ;
152
+ }
153
+ return null ;
114
154
}
115
155
116
156
int IList < string > . IndexOf ( string item )
@@ -120,22 +160,29 @@ int IList<string>.IndexOf(string item)
120
160
121
161
private int IndexOf ( string item )
122
162
{
123
- if ( _values != null )
163
+ var arrayValue = _value as string [ ] ;
164
+ if ( arrayValue != null )
124
165
{
125
- var values = _values ;
126
- for ( int i = 0 ; i < values . Length ; i ++ )
166
+ for ( int i = 0 ; i < arrayValue . Length ; i ++ )
127
167
{
128
- if ( string . Equals ( values [ i ] , item , StringComparison . Ordinal ) )
168
+ if ( string . Equals ( arrayValue [ i ] , item , StringComparison . Ordinal ) )
129
169
{
130
170
return i ;
131
171
}
132
172
}
133
173
return - 1 ;
134
174
}
135
175
136
- if ( _value != null )
176
+ return IndexOfString ( item ) ;
177
+ }
178
+
179
+ [ MethodImpl ( MethodImplOptions . NoInlining ) ]
180
+ private int IndexOfString ( string item )
181
+ {
182
+ var stringVal = _value as string ;
183
+ if ( stringVal != null )
137
184
{
138
- return string . Equals ( _value , item , StringComparison . Ordinal ) ? 0 : - 1 ;
185
+ return string . Equals ( stringVal , item , StringComparison . Ordinal ) ? 0 : - 1 ;
139
186
}
140
187
141
188
return - 1 ;
@@ -153,13 +200,15 @@ void ICollection<string>.CopyTo(string[] array, int arrayIndex)
153
200
154
201
private void CopyTo ( string [ ] array , int arrayIndex )
155
202
{
156
- if ( _values != null )
203
+ var arrayValue = _value as string [ ] ;
204
+ if ( arrayValue != null )
157
205
{
158
- Array . Copy ( _values , 0 , array , arrayIndex , _values . Length ) ;
206
+ Array . Copy ( arrayValue , 0 , array , arrayIndex , arrayValue . Length ) ;
159
207
return ;
160
208
}
161
209
162
- if ( _value != null )
210
+ var stringVal = _value as string ;
211
+ if ( stringVal != null )
163
212
{
164
213
if ( array == null )
165
214
{
@@ -175,7 +224,7 @@ private void CopyTo(string[] array, int arrayIndex)
175
224
$ "'{ nameof ( array ) } ' is not long enough to copy all the items in the collection. Check '{ nameof ( arrayIndex ) } ' and '{ nameof ( array ) } ' length.") ;
176
225
}
177
226
178
- array [ arrayIndex ] = _value ;
227
+ array [ arrayIndex ] = stringVal ;
179
228
}
180
229
}
181
230
@@ -221,18 +270,27 @@ IEnumerator IEnumerable.GetEnumerator()
221
270
222
271
public static bool IsNullOrEmpty ( StringValues value )
223
272
{
224
- if ( value . _values == null )
273
+ var stringVal = value . _value as string ;
274
+ if ( stringVal != null )
225
275
{
226
- return string . IsNullOrEmpty ( value . _value ) ;
276
+ return string . IsNullOrEmpty ( stringVal ) ;
227
277
}
228
- switch ( value . _values . Length )
278
+
279
+ return value . IsNullOrEmptyArray ( ) ;
280
+ }
281
+
282
+ [ MethodImpl ( MethodImplOptions . NoInlining ) ]
283
+ private bool IsNullOrEmptyArray ( )
284
+ {
285
+ var arrayValue = _value as string [ ] ;
286
+ switch ( arrayValue . Length )
229
287
{
230
288
case 0 : return true ;
231
- case 1 : return string . IsNullOrEmpty ( value . _values [ 0 ] ) ;
289
+ case 1 : return string . IsNullOrEmpty ( arrayValue [ 0 ] ) ;
232
290
default : return false ;
233
291
}
234
292
}
235
-
293
+
236
294
public static StringValues Concat ( StringValues values1 , StringValues values2 )
237
295
{
238
296
var count1 = values1 . Count ;
@@ -405,17 +463,24 @@ public override bool Equals(object obj)
405
463
406
464
public override int GetHashCode ( )
407
465
{
408
- if ( _values == null )
466
+ var stringVal = _value as string ;
467
+ if ( stringVal != null )
409
468
{
410
- return _value == null ? 0 : _value . GetHashCode ( ) ;
469
+ return stringVal . GetHashCode ( ) ;
411
470
}
412
471
413
- var hcc = new HashCodeCombiner ( ) ;
414
- for ( var i = 0 ; i < _values . Length ; i ++ )
472
+ var arrayValue = _value as string [ ] ;
473
+ if ( arrayValue != null )
415
474
{
416
- hcc . Add ( _values [ i ] ) ;
475
+ var hcc = new HashCodeCombiner ( ) ;
476
+ for ( var i = 0 ; i < arrayValue . Length ; i ++ )
477
+ {
478
+ hcc . Add ( arrayValue [ i ] ) ;
479
+ }
480
+ return hcc . CombinedHash ;
417
481
}
418
- return hcc . CombinedHash ;
482
+
483
+ return 0 ;
419
484
}
420
485
421
486
public struct Enumerator : IEnumerator < string >
@@ -426,8 +491,8 @@ public struct Enumerator : IEnumerator<string>
426
491
427
492
public Enumerator ( ref StringValues values )
428
493
{
429
- _values = values . _values ;
430
- _current = values . _value ;
494
+ _current = values . _value as string ;
495
+ _values = values . _value as string [ ] ;
431
496
_index = 0 ;
432
497
}
433
498
0 commit comments