Skip to content

Commit 4978c02

Browse files
twsouthwicktomjebo
authored andcommitted
Use a central cache of empty collections (#356)
1 parent a02ccfc commit 4978c02

File tree

15 files changed

+103
-251
lines changed

15 files changed

+103
-251
lines changed

DocumentFormat.OpenXml.Tests/OpenXmlDomTest/PackageReflector.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ internal void ReflectPart(OpenXmlPart srcPart, OpenXmlPart destPart, OpenXmlPart
444444

445445
// Load source part into source root element
446446
var loader = rootType.GetMethod("Load", new Type[] { srcPartType });
447-
var ctor = rootType.GetConstructor(new Type[] { });
447+
var ctor = rootType.GetConstructor(Cached.Array<Type>());
448448
OpenXmlElement srcRoot = ctor.Invoke(null) as OpenXmlElement;
449449
loader.Invoke(srcRoot, new Object[] { srcPart });
450450

DocumentFormat.OpenXml.Tests/ofapiTest/OpenXmlElementTest.cs

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -703,14 +703,9 @@ public void ChildElementsTest()
703703
var unknown2 = unknown1.AppendChild(new OpenXmlUnknownElement("tmp:node2", "http://temp"));
704704
var miscNode = p.AppendChild(new OpenXmlMiscNode(System.Xml.XmlNodeType.Comment, "<!-- comment -->"));
705705

706-
var emptyListSingleton = EmptyElementList.EmptyElementListSingleton;
707-
var emptyEnumeratorSingleton = EmptyEnumerator<OpenXmlElement>.EmptyEnumeratorSingleton;
708-
709-
Assert.NotSame(emptyListSingleton, p.ChildElements);
710706
Assert.Equal(4, p.ChildElements.Count);
711707

712708
var enumerator = p.ChildElements.GetEnumerator();
713-
Assert.NotSame(emptyEnumeratorSingleton, enumerator);
714709
Assert.True(enumerator.MoveNext());
715710
Assert.Same(pPr, enumerator.Current);
716711

@@ -721,60 +716,47 @@ public void ChildElementsTest()
721716
Assert.False(enumerator.MoveNext()); // the end
722717

723718
// pPr, empty children
724-
Assert.Same(emptyListSingleton, pPr.ChildElements);
725-
Assert.Equal(0, pPr.ChildElements.Count);
719+
Assert.Empty(pPr.ChildElements);
720+
Assert.Same(OpenXmlElementList.Empty, pPr.ChildElements);
726721
enumerator = pPr.ChildElements.GetEnumerator();
727-
Assert.Same(emptyEnumeratorSingleton, enumerator);
728722
Assert.False(enumerator.MoveNext());
729723

730724
// r, two child
731-
Assert.NotSame(emptyListSingleton, r.ChildElements);
732725
Assert.Equal(2, r.ChildElements.Count);
733726
enumerator = r.ChildElements.GetEnumerator();
734-
Assert.NotSame(emptyEnumeratorSingleton, enumerator);
735727
Assert.True(enumerator.MoveNext());
736728
Assert.Same(rPr, enumerator.Current);
737729

738730
// rPr, one child
739-
Assert.NotSame(emptyListSingleton, rPr.ChildElements);
740731
Assert.Equal(1, rPr.ChildElements.Count);
741732
enumerator = rPr.ChildElements.GetEnumerator();
742-
Assert.NotSame(emptyEnumeratorSingleton, enumerator);
743733
Assert.True(enumerator.MoveNext());
744734

745735
// b, leaf element
746-
Assert.Same(emptyListSingleton, b.ChildElements);
747736
Assert.Equal(0, b.ChildElements.Count);
748737
enumerator = b.ChildElements.GetEnumerator();
749-
Assert.Same(emptyEnumeratorSingleton, enumerator);
750738
Assert.False(enumerator.MoveNext());
751739

752740
// t, leaf text element
753-
Assert.Same(emptyListSingleton, t.ChildElements);
754741
Assert.Equal(0, t.ChildElements.Count);
755742
enumerator = t.ChildElements.GetEnumerator();
756-
Assert.Same(emptyEnumeratorSingleton, enumerator);
757743
Assert.False(enumerator.MoveNext());
758744

759745
// unknown1, one child
760-
Assert.NotSame(emptyListSingleton, unknown1.ChildElements);
761746
Assert.Equal(1, unknown1.ChildElements.Count);
762747
enumerator = unknown1.ChildElements.GetEnumerator();
763-
Assert.NotSame(emptyEnumeratorSingleton, enumerator);
764748
Assert.True(enumerator.MoveNext());
765749

766750
// unknown2, empty children
767-
Assert.Same(emptyListSingleton, unknown2.ChildElements);
751+
Assert.Same(OpenXmlElementList.Empty, unknown2.ChildElements);
768752
Assert.Equal(0, unknown2.ChildElements.Count);
769753
enumerator = unknown2.ChildElements.GetEnumerator();
770-
Assert.Same(emptyEnumeratorSingleton, enumerator);
771754
Assert.False(enumerator.MoveNext());
772755

773756
// miscNode
774-
Assert.Same(emptyListSingleton, miscNode.ChildElements);
757+
Assert.Same(OpenXmlElementList.Empty, miscNode.ChildElements);
775758
Assert.Equal(0, miscNode.ChildElements.Count);
776759
enumerator = miscNode.ChildElements.GetEnumerator();
777-
Assert.Same(emptyEnumeratorSingleton, enumerator);
778760
Assert.False(enumerator.MoveNext());
779761
}
780762

DocumentFormat.OpenXml/AlternateContent.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ internal override byte NamespaceId
109109
get { return MarkupCompatibilityNamespaceId; }
110110
}
111111

112-
private static string[] attributeTagNames = { };
113-
private static byte[] attributeNamespaceIds = { };
112+
private static string[] attributeTagNames = Cached.Array<string>();
113+
private static byte[] attributeNamespaceIds = Cached.Array<byte>();
114114

115115
internal override string[] AttributeTagNames
116116
{

DocumentFormat.OpenXml/AlternateContentFallback.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) Microsoft. All rights reserved.
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

4+
using System;
45
using System.Collections.Generic;
56

67
namespace DocumentFormat.OpenXml
@@ -75,8 +76,8 @@ internal override byte NamespaceId
7576
get { return AlternateContent.MarkupCompatibilityNamespaceId; }
7677
}
7778

78-
private static string[] attributeTagNames = { };
79-
private static byte[] attributeNamespaceIds = { };
79+
private static string[] attributeTagNames = Cached.Array<string>();
80+
private static byte[] attributeNamespaceIds = Cached.Array<byte>();
8081

8182
internal override string[] AttributeTagNames
8283
{

DocumentFormat.OpenXml/Cached.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System.Collections.ObjectModel;
5+
6+
namespace DocumentFormat.OpenXml
7+
{
8+
internal static class Cached
9+
{
10+
#if FEATURE_ARRAY_EMPTY
11+
public static T[] Array<T>() => System.Array.Empty<T>();
12+
#else
13+
public static T[] Array<T>() => EmptyArray<T>.Value;
14+
15+
private static class EmptyArray<T>
16+
{
17+
internal static readonly T[] Value = new T[0];
18+
}
19+
#endif
20+
21+
public static ReadOnlyCollection<T> ReadOnlyCollection<T>() => ReadOnlyCollectionCache<T>.Value;
22+
23+
private static class ReadOnlyCollectionCache<T>
24+
{
25+
internal static ReadOnlyCollection<T> Value = new ReadOnlyCollection<T>(Array<T>());
26+
}
27+
}
28+
}

DocumentFormat.OpenXml/DocumentFormat.OpenXml.csproj

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<TargetFrameworks Condition=" '$(ProjectLoadStyle)' == 'DevCore' ">netstandard1.3</TargetFrameworks>
1212
<TargetFrameworks Condition=" '$(ProjectLoadStyle)' == 'DevFramework' ">net46</TargetFrameworks>
1313
<TargetFrameworks Condition=" '$(ProjectLoadStyle)' == 'All' ">netstandard1.3;net35;net40;net46</TargetFrameworks>
14-
14+
1515
<NoWarn>$(NoWarn);3003</NoWarn>
1616
<GenerateDocumentationFile>true</GenerateDocumentationFile>
1717
</PropertyGroup>
@@ -29,6 +29,7 @@
2929
constants are used to conditionally compile features:
3030
3131
FEATURE_ABSTRACT_XML_CLOSE : XmlWriter.Close is defined as abstract
32+
FEATURE_ARRAY_EMPTY : Array.Empty exists
3233
FEATURE_CLOSE : Stream.Close is available in the platform
3334
FEATURE_DCS_SETTINGS : DataContractSerializer settings class exists
3435
FEATURE_SERIALIZATION : Serialization using ISerializable is in the platform
@@ -68,7 +69,7 @@
6869

6970
<When Condition=" '$(TargetFramework)' == 'net46' ">
7071
<PropertyGroup>
71-
<DefineConstants>$(DefineConstants);FEATURE_DCS_SETTINGS;FEATURE_CLOSE;FEATURE_SERIALIZATION;FEATURE_SYSTEMEXCEPTION;FEATURE_XML_QUOTECHAR;FEATURE_XML_SCHEMA;FEATURE_XML_VERIFYTOKEN</DefineConstants>
72+
<DefineConstants>$(DefineConstants);FEATURE_ARRAY_EMPTY;FEATURE_DCS_SETTINGS;FEATURE_CLOSE;FEATURE_SERIALIZATION;FEATURE_SYSTEMEXCEPTION;FEATURE_XML_QUOTECHAR;FEATURE_XML_SCHEMA;FEATURE_XML_VERIFYTOKEN</DefineConstants>
7273
</PropertyGroup>
7374

7475
<ItemGroup Condition=" '$(TargetFramework)' == 'net46' ">
@@ -85,7 +86,7 @@
8586

8687
<When Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
8788
<PropertyGroup>
88-
<DefineConstants> $(DefineConstants);FEATURE_DCS_SETTINGS</DefineConstants>
89+
<DefineConstants> $(DefineConstants);FEATURE_DCS_SETTINGS;FEATURE_ARRAY_EMPTY</DefineConstants>
8990
</PropertyGroup>
9091

9192
<ItemGroup>

DocumentFormat.OpenXml/EmptyElementList.cs

Lines changed: 0 additions & 43 deletions
This file was deleted.

DocumentFormat.OpenXml/EmptyEnumerable.cs

Lines changed: 0 additions & 40 deletions
This file was deleted.

DocumentFormat.OpenXml/EmptyEnumerator.cs

Lines changed: 0 additions & 73 deletions
This file was deleted.

DocumentFormat.OpenXml/OpenXmlDomReader.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Collections.Generic;
66
using System.Collections.ObjectModel;
77
using System.Diagnostics;
8+
using System.Linq;
89

910
namespace DocumentFormat.OpenXml
1011
{
@@ -115,7 +116,7 @@ public override IEnumerable<KeyValuePair<string, string>> NamespaceDeclarations
115116
}
116117
else
117118
{
118-
return EmptyEnumerable<KeyValuePair<string, string>>.EmptyEnumerableSingleton;
119+
return Enumerable.Empty<KeyValuePair<string, string>>();
119120
}
120121
}
121122
}

0 commit comments

Comments
 (0)