Skip to content

Commit 7c2c48b

Browse files
authored
Inherit DisposableSet from List<> to save an allocation (#341)
1 parent ea0f70e commit 7c2c48b

File tree

1 file changed

+14
-49
lines changed

1 file changed

+14
-49
lines changed

Orm/Xtensive.Orm/Core/DisposableSet.cs

Lines changed: 14 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,6 @@
44
// Created by: Alex Yakunin
55
// Created: 2007.12.29
66

7-
using System;
8-
using System.Collections;
9-
using System.Collections.Generic;
10-
using System.Threading.Tasks;
11-
using Xtensive.Core;
12-
13-
147
namespace Xtensive.Core
158
{
169
/// <summary>
@@ -22,24 +15,23 @@ namespace Xtensive.Core
2215
/// <see cref="IDisposable.Dispose"/> methods are invoked in backward order.
2316
/// </note>
2417
/// </remarks>
25-
public sealed class DisposableSet : IDisposable, IAsyncDisposable
18+
internal sealed class DisposableSet() : List<IDisposable>, IDisposable, IAsyncDisposable
2619
{
2720
private HashSet<IDisposable> set;
28-
private List<IDisposable> list;
2921

3022
/// <summary>
3123
/// Adds an <see cref="IDisposable"/> object to the set.
3224
/// </summary>
3325
/// <param name="disposable">The object to add.</param>
3426
/// <returns><see langword="True"/>, if object is successfully added;
3527
/// otherwise, <see langword="false"/>.</returns>
36-
public bool Add(IDisposable disposable)
28+
public new bool Add(IDisposable disposable)
3729
{
3830
if (disposable==null)
3931
return false;
4032
EnsureInitialized();
4133
if (set.Add(disposable)) {
42-
list.Add(disposable);
34+
base.Add(disposable);
4335
return true;
4436
}
4537
return false;
@@ -49,10 +41,10 @@ public bool Add(IDisposable disposable)
4941
/// Clears this instance by discarding all registered objects.
5042
/// <see cref="IDisposable.Dispose"/> methods are not called.
5143
/// </summary>
52-
public void Clear()
44+
public new void Clear()
5345
{
5446
set = null;
55-
list = null;
47+
base.Clear();
5648
}
5749

5850
/// <summary>
@@ -69,32 +61,7 @@ public void Clear()
6961

7062
private void EnsureInitialized()
7163
{
72-
if (set==null) {
73-
set = new HashSet<IDisposable>();
74-
list = new List<IDisposable>();
75-
}
76-
}
77-
78-
79-
// Constructors
80-
81-
/// <summary>
82-
/// Initializes new instance of this type.
83-
/// </summary>
84-
/// <param name="initialContent">The initial content.</param>
85-
public DisposableSet(IEnumerable initialContent)
86-
: this()
87-
{
88-
ArgumentNullException.ThrowIfNull(initialContent);
89-
foreach (object o in initialContent)
90-
Add(o as IDisposable);
91-
}
92-
93-
/// <summary>
94-
/// Initializes new instance of this type.
95-
/// </summary>
96-
public DisposableSet()
97-
{
64+
set ??= new();
9865
}
9966

10067
/// <summary>
@@ -103,34 +70,33 @@ public DisposableSet()
10370
void IDisposable.Dispose()
10471
{
10572
try {
106-
if (list==null) {
73+
if (Count == 0) {
10774
return;
10875
}
10976

11077
using (var aggregator = new ExceptionAggregator()) {
111-
for (var i = list.Count - 1; i >= 0; i--) {
112-
aggregator.Execute(d => d.Dispose(), list[i]);
78+
for (var i = Count - 1; i >= 0; i--) {
79+
aggregator.Execute(d => d.Dispose(), this[i]);
11380
}
11481

11582
aggregator.Complete();
11683
}
11784
}
11885
finally {
119-
set = null;
120-
list = null;
86+
Clear();
12187
}
12288
}
12389

12490
async ValueTask IAsyncDisposable.DisposeAsync()
12591
{
12692
try {
127-
if (list==null) {
93+
if (Count == 0) {
12894
return;
12995
}
13096

13197
using (var aggregator = new ExceptionAggregator()) {
132-
for (var i = list.Count - 1; i >= 0; i--) {
133-
var disposable = list[i];
98+
for (var i = Count - 1; i >= 0; i--) {
99+
var disposable = this[i];
134100
if (disposable is IAsyncDisposable asyncDisposable) {
135101
await aggregator.ExecuteAsync(d => d.DisposeAsync(), asyncDisposable).ConfigureAwaitFalse();
136102
}
@@ -143,8 +109,7 @@ async ValueTask IAsyncDisposable.DisposeAsync()
143109
}
144110
}
145111
finally {
146-
set = null;
147-
list = null;
112+
Clear();
148113
}
149114
}
150115
}

0 commit comments

Comments
 (0)