@@ -100,31 +100,52 @@ public static String Join(String separator, params Object[] values) {
100
100
}
101
101
102
102
[ ComVisible ( false ) ]
103
- public static String Join < T > ( String separator , IEnumerable < T > values ) {
103
+ public static String Join < T > ( String separator , IEnumerable < T > values )
104
+ {
104
105
if ( values == null )
105
106
throw new ArgumentNullException ( "values" ) ;
106
107
Contract . Ensures ( Contract . Result < String > ( ) != null ) ;
107
108
Contract . EndContractBlock ( ) ;
108
109
109
- using ( IEnumerator < T > en = values . GetEnumerator ( ) ) {
110
+ using ( IEnumerator < T > en = values . GetEnumerator ( ) )
111
+ {
110
112
if ( ! en . MoveNext ( ) )
111
- return String . Empty ;
112
-
113
- StringBuilder result = StringBuilderCache . Acquire ( ) ;
113
+ return string . Empty ;
114
+
115
+ // We called MoveNext once, so this will be the first item
114
116
T currentValue = en . Current ;
115
117
116
- if ( currentValue != null ) {
117
- result . Append ( currentValue . ToString ( ) ) ;
118
+ // Call ToString before calling MoveNext again, since
119
+ // we want to stay consistent with the below loop
120
+ // Everything should be called in the order
121
+ // MoveNext-Current-ToString, unless further optimizations
122
+ // can be made, to avoid breaking changes
123
+ string firstString = currentValue ? . ToString ( ) ;
124
+
125
+ // If there's only 1 item, simply call ToString on that
126
+ if ( ! en . MoveNext ( ) )
127
+ {
128
+ // We have to handle the case of either currentValue
129
+ // or its ToString being null
130
+ return firstString ?? string . Empty ;
118
131
}
119
132
120
- while ( en . MoveNext ( ) ) {
133
+ StringBuilder result = StringBuilderCache . Acquire ( ) ;
134
+
135
+ result . Append ( firstString ) ;
136
+
137
+ do
138
+ {
121
139
currentValue = en . Current ;
122
140
123
141
result . Append ( separator ) ;
124
- if ( currentValue != null ) {
142
+ if ( currentValue != null )
143
+ {
125
144
result . Append ( currentValue . ToString ( ) ) ;
126
145
}
127
- }
146
+ }
147
+ while ( en . MoveNext ( ) ) ;
148
+
128
149
return StringBuilderCache . GetStringAndRelease ( result ) ;
129
150
}
130
151
}
@@ -161,15 +182,6 @@ public static String Join(String separator, IEnumerable<String> values) {
161
182
}
162
183
}
163
184
164
-
165
- #if BIT64
166
- private const int charPtrAlignConst = 3 ;
167
- private const int alignConst = 7 ;
168
- #else
169
- private const int charPtrAlignConst = 1 ;
170
- private const int alignConst = 3 ;
171
- #endif
172
-
173
185
internal char FirstChar { get { return m_firstChar ; } }
174
186
175
187
// Joins an array of strings together as one string with a separator between each original string.
0 commit comments