Skip to content
This repository was archived by the owner on Nov 20, 2018. It is now read-only.

Commit eb4ac33

Browse files
committed
Reduce boxing, Pre-box Empty enumerators
1 parent 4354dbb commit eb4ac33

File tree

3 files changed

+92
-29
lines changed

3 files changed

+92
-29
lines changed

src/Microsoft.AspNet.Http/Features/FormFeature.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public IFormCollection ReadForm()
8484

8585
if (!HasFormContentType)
8686
{
87-
throw new InvalidOperationException("Incorrect Content-Type: " + _request.ContentType);
87+
throw new InvalidOperationException($"Incorrect Content-Type: {_request.ContentType}");
8888
}
8989

9090
// TODO: Avoid Sync-over-Async http://blogs.msdn.com/b/pfxteam/archive/2012/04/13/10293638.aspx
@@ -115,7 +115,7 @@ private async Task<IFormCollection> InnerReadFormAsync(CancellationToken cancell
115115
{
116116
if (!HasFormContentType)
117117
{
118-
throw new InvalidOperationException("Incorrect Content-Type: " + _request.ContentType);
118+
throw new InvalidOperationException($"Incorrect Content-Type: {_request.ContentType}");
119119
}
120120

121121
cancellationToken.ThrowIfCancellationRequested();
@@ -126,7 +126,7 @@ private async Task<IFormCollection> InnerReadFormAsync(CancellationToken cancell
126126
FormFileCollection files = null;
127127

128128
// Some of these code paths use StreamReader which does not support cancellation tokens.
129-
using (cancellationToken.Register(_request.HttpContext.Abort))
129+
using (cancellationToken.Register((Action)_request.HttpContext.Abort))
130130
{
131131
var contentType = ContentType;
132132
// Check the content-type
@@ -179,7 +179,7 @@ private async Task<IFormCollection> InnerReadFormAsync(CancellationToken cancell
179179
}
180180
else
181181
{
182-
System.Diagnostics.Debug.Assert(false, "Unrecognized content-disposition for this section: " + section.ContentDisposition);
182+
System.Diagnostics.Debug.Assert(false, $"Unrecognized content-disposition for this section: {section.ContentDisposition}");
183183
}
184184

185185
section = await multipartReader.ReadNextSectionAsync(cancellationToken);

src/Microsoft.AspNet.Http/ReadableStringCollection.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ public class ReadableStringCollection : IReadableStringCollection
1818
#if !DNXCORE50
1919
private static readonly string[] EmptyKeys = new string[0];
2020
#endif
21-
private static readonly IEnumerable<KeyValuePair<string, StringValues>> EmptyEnumerable = new KeyValuePair<string, StringValues>[0];
21+
// Pre-box empty case
22+
private static readonly IEnumerator<KeyValuePair<string, StringValues>> EmptyEnumerator
23+
= ((IEnumerable<KeyValuePair<string, StringValues>>)new KeyValuePair<string, StringValues>[0]).GetEnumerator();
2224

2325
internal ReadableStringCollection()
2426
{
@@ -126,7 +128,7 @@ public IEnumerator<KeyValuePair<string, StringValues>> GetEnumerator()
126128
{
127129
if (Store == null)
128130
{
129-
return EmptyEnumerable.GetEnumerator();
131+
return EmptyEnumerator;
130132
}
131133

132134
return Store.GetEnumerator();

src/Microsoft.AspNet.WebUtilities/SafeLazyDictionary.cs

Lines changed: 84 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,13 @@ internal class SafeLazyDictionary<TValue> : IDictionary<string, TValue>
1212
#if !DNXCORE50
1313
private static readonly string[] EmptyKeys = new string[0];
1414
private static readonly TValue[] EmptyValues = new TValue[0];
15-
private static readonly KeyValuePair<string, TValue>[] EmptyEnumerator = new KeyValuePair<string, TValue>[0];
1615
#endif
17-
public IDictionary<string, TValue> Store { get; set; }
16+
private static readonly Enumerator EmptyEnumerator = new Enumerator();
17+
// Pre-box
18+
private static readonly IEnumerator<KeyValuePair<string, TValue>> EmptyIEnumeratorType = EmptyEnumerator;
19+
private static readonly IEnumerator EmptyIEnumerator = EmptyEnumerator;
20+
21+
private Dictionary<string, TValue> Store { get; set; }
1822

1923
public SafeLazyDictionary()
2024
{
@@ -133,11 +137,14 @@ public void Clear()
133137

134138
public bool Contains(KeyValuePair<string, TValue> item)
135139
{
136-
if (Store == null)
140+
TValue value;
141+
if (Store == null ||
142+
!Store.TryGetValue(item.Key, out value) ||
143+
!value.Equals(item.Value))
137144
{
138145
return false;
139146
}
140-
return Store.Contains(item);
147+
return true;
141148
}
142149

143150
public bool ContainsKey(string key)
@@ -162,20 +169,7 @@ public void CopyTo(KeyValuePair<string, TValue>[] array, int arrayIndex)
162169
arrayIndex++;
163170
}
164171
}
165-
166-
public IEnumerator<KeyValuePair<string, TValue>> GetEnumerator()
167-
{
168-
if (Store == null)
169-
{
170-
#if DNXCORE50
171-
return ((IEnumerable<KeyValuePair<string, TValue>>)Array.Empty<KeyValuePair<string, TValue>>()).GetEnumerator();
172-
#else
173-
return ((IEnumerable<KeyValuePair<string, TValue>>)EmptyEnumerator).GetEnumerator();
174-
#endif
175-
}
176-
return Store.GetEnumerator();
177-
}
178-
172+
179173
public bool Remove(KeyValuePair<string, TValue> item)
180174
{
181175
if (Store == null)
@@ -211,17 +205,84 @@ public bool TryGetValue(string key, out TValue value)
211205
return Store.TryGetValue(key, out value);
212206
}
213207

208+
public Enumerator GetEnumerator()
209+
{
210+
if (Store == null)
211+
{
212+
return EmptyEnumerator;
213+
}
214+
return new Enumerator(Store.GetEnumerator());
215+
}
216+
217+
IEnumerator<KeyValuePair<string, TValue>> IEnumerable<KeyValuePair<string, TValue>>.GetEnumerator()
218+
{
219+
if (Store == null)
220+
{
221+
return EmptyIEnumeratorType;
222+
}
223+
return Store.GetEnumerator();
224+
}
214225
IEnumerator IEnumerable.GetEnumerator()
215226
{
216227
if (Store == null)
217228
{
218-
#if DNXCORE50
219-
return Array.Empty<TValue>().GetEnumerator();
220-
#else
221-
return EmptyEnumerator.GetEnumerator();
222-
#endif
229+
return EmptyIEnumerator;
223230
}
224231
return Store.GetEnumerator();
225232
}
233+
234+
public struct Enumerator : IEnumerator<KeyValuePair<string, TValue>>
235+
{
236+
// Do NOT make this readonly, or MoveNext will not work
237+
private Dictionary<string, TValue>.Enumerator _dictionaryEnumerator;
238+
private bool _notEmpty;
239+
240+
internal Enumerator(Dictionary<string, TValue>.Enumerator dictionaryEnumerator)
241+
{
242+
_dictionaryEnumerator = dictionaryEnumerator;
243+
_notEmpty = true;
244+
}
245+
246+
public bool MoveNext()
247+
{
248+
if (_notEmpty)
249+
{
250+
return _dictionaryEnumerator.MoveNext();
251+
}
252+
return false;
253+
}
254+
255+
public KeyValuePair<string, TValue> Current
256+
{
257+
get
258+
{
259+
if (_notEmpty)
260+
{
261+
return _dictionaryEnumerator.Current;
262+
}
263+
return default(KeyValuePair<string, TValue>);
264+
}
265+
}
266+
267+
public void Dispose()
268+
{
269+
}
270+
271+
object IEnumerator.Current
272+
{
273+
get
274+
{
275+
return Current;
276+
}
277+
}
278+
279+
void IEnumerator.Reset()
280+
{
281+
if (_notEmpty)
282+
{
283+
((IEnumerator)_dictionaryEnumerator).Reset();
284+
}
285+
}
286+
}
226287
}
227288
}

0 commit comments

Comments
 (0)