Skip to content

Commit 4669889

Browse files
authored
Optimization: Use type covariance implementing Clone() to avoid casting (#237)
* Optimization: Use type covarianve to avoid casting * Shorter form * parameterless ctor for TrackingStackFrame() * Check for source.RawData * Convert `ChangedValue` to record syntax * Null check RawData * Refactor SqlNode.Clone() * Refactor SqlNode.Clone() * Use type inference
1 parent 1604d2c commit 4669889

File tree

146 files changed

+353
-485
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

146 files changed

+353
-485
lines changed

Extensions/Xtensive.Orm.BulkOperations/Internals/QueryOperation.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ private void JoinViaIn(SqlStatement statement, SqlSelect select)
140140
var indexMapping = PrimaryIndexes[0];
141141
var columns = new List<ColumnInfo>();
142142
foreach (var columnInfo in indexMapping.PrimaryIndex.KeyColumns.Keys) {
143-
var s = (SqlSelect) select.Clone();
143+
var s = (SqlSelect)((ICloneable)select).Clone();
144144
foreach (var column in columns) {
145145
var ex = SqlDml.Equals(s.From.Columns[column.Name], table.Columns[column.Name]);
146146
s.Where = s.Where is null ? ex : SqlDml.And(s.Where, ex);

Extensions/Xtensive.Orm.Tracking.Tests/TrackingStackFrameTests.cs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public class TrackingStackFrameTests : TrackingTestBase
1111
[Test]
1212
public void SafelyInsertTheSameItemTwiceTest()
1313
{
14-
var frame = new TrackingStackFrame(false);
14+
var frame = new TrackingStackFrame();
1515
var key = Key.Create(Domain, typeof(MyEntity), 1);
1616
var item = CreateTrackingItem(key, TrackingItemState.Created);
1717
frame.Register(item);
@@ -21,8 +21,8 @@ public void SafelyInsertTheSameItemTwiceTest()
2121
[Test]
2222
public void MergeTwoEmptyFramesTest()
2323
{
24-
var target = new TrackingStackFrame(false);
25-
var source = new TrackingStackFrame(false);
24+
var target = new TrackingStackFrame();
25+
var source = new TrackingStackFrame();
2626
target.MergeWith(source);
2727

2828
Assert.AreEqual(0, target.Count);
@@ -32,9 +32,9 @@ public void MergeTwoEmptyFramesTest()
3232
public void MergeEmptyFrameWithNonEmptyFrameTest()
3333
{
3434
var key = Key.Create(Domain, typeof(MyEntity), 1);
35-
var target = new TrackingStackFrame(false);
35+
var target = new TrackingStackFrame();
3636

37-
var source = new TrackingStackFrame(false);
37+
var source = new TrackingStackFrame();
3838
source.Register(CreateTrackingItem(key, TrackingItemState.Created));
3939

4040
target.MergeWith(source);
@@ -46,11 +46,11 @@ public void MergeEmptyFrameWithNonEmptyFrameTest()
4646
public void MergeNonEmptyFrameWithEmptyFrameTest()
4747
{
4848
var key = Key.Create(Domain, typeof(MyEntity), 1);
49-
var target = new TrackingStackFrame(false);
49+
var target = new TrackingStackFrame();
5050
target.Register(CreateTrackingItem(key, TrackingItemState.Created));
5151
var count = target.Count;
5252

53-
var source = new TrackingStackFrame(false);
53+
var source = new TrackingStackFrame();
5454

5555
target.MergeWith(source);
5656

@@ -61,11 +61,11 @@ public void MergeNonEmptyFrameWithEmptyFrameTest()
6161
public void MergeFramesWithTheSameItemsTest()
6262
{
6363
var key = Key.Create(Domain, typeof(MyEntity), 1);
64-
var target = new TrackingStackFrame(false);
64+
var target = new TrackingStackFrame();
6565
target.Register(CreateTrackingItem(key, TrackingItemState.Created));
6666
var count = target.Count;
6767

68-
var source = new TrackingStackFrame(false);
68+
var source = new TrackingStackFrame();
6969
source.Register(CreateTrackingItem(key, TrackingItemState.Changed));
7070

7171
target.MergeWith(source);
@@ -79,10 +79,10 @@ public void MergeFramesWithDifferentItemsTest()
7979
{
8080
var key1 = Key.Create(Domain, typeof(MyEntity), 1);
8181
var key2 = Key.Create(Domain, typeof(MyEntity), 2);
82-
var target = new TrackingStackFrame(false);
82+
var target = new TrackingStackFrame();
8383
target.Register(CreateTrackingItem(key1, TrackingItemState.Created));
8484

85-
var source = new TrackingStackFrame(false);
85+
var source = new TrackingStackFrame();
8686
source.Register(CreateTrackingItem(key2, TrackingItemState.Changed));
8787
var count = target.Count + source.Count;
8888

Extensions/Xtensive.Orm.Tracking/ChangedValue.cs

Lines changed: 5 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,39 +4,9 @@
44

55
using Xtensive.Orm.Model;
66

7-
namespace Xtensive.Orm.Tracking
8-
{
9-
/// <summary>
10-
/// Represents a pair of original and changed values for a persistent field
11-
/// </summary>
12-
public readonly struct ChangedValue
13-
{
14-
/// <summary>
15-
/// Gets the field.
16-
/// </summary>
17-
public FieldInfo Field { get; }
7+
namespace Xtensive.Orm.Tracking;
188

19-
/// <summary>
20-
/// Gets the original value.
21-
/// </summary>
22-
public object OriginalValue { get; }
23-
24-
/// <summary>
25-
/// Gets the new value.
26-
/// </summary>
27-
public object NewValue { get; }
28-
29-
/// <summary>
30-
/// Initializes a new instance of the <see cref="ChangedValue"/> class.
31-
/// </summary>
32-
/// <param name="field">The field.</param>
33-
/// <param name="originalValue">The original value.</param>
34-
/// <param name="newValue">The new value.</param>
35-
public ChangedValue(FieldInfo field, object originalValue, object newValue)
36-
{
37-
Field = field;
38-
OriginalValue = originalValue;
39-
NewValue = newValue;
40-
}
41-
}
42-
}
9+
/// <summary>
10+
/// Represents a pair of original and changed values for a persistent field
11+
/// </summary>
12+
public readonly record struct ChangedValue(FieldInfo Field, object OriginalValue, object NewValue);

Extensions/Xtensive.Orm.Tracking/Internals/SessionTrackingMonitor.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System;
66
using System.Collections.Generic;
77
using System.Linq;
8+
using Xtensive.Core;
89
using Xtensive.IoC;
910
using Xtensive.Orm.Services;
1011

@@ -28,7 +29,7 @@ private void Subscribe()
2829

2930
private void OnOpenTransaction(object sender, TransactionEventArgs e)
3031
{
31-
stack.Push(new TrackingStackFrame(false));
32+
stack.Push(new TrackingStackFrame());
3233
}
3334

3435
private void OnCommitTransaction(object sender, TransactionEventArgs e)
@@ -40,7 +41,7 @@ private void OnCommitTransaction(object sender, TransactionEventArgs e)
4041
if (e.Transaction.IsNested)
4142
return;
4243

43-
var items = target.Cast<ITrackingItem>().ToList().AsReadOnly();
44+
var items = target.Cast<ITrackingItem>().ToList().AsSafeWrapper();
4445
target.Clear();
4546

4647
RaiseTrackingCompleted(new TrackingCompletedEventArgs(session, items));
@@ -82,7 +83,7 @@ public SessionTrackingMonitor(Session session, DirectSessionAccessor accessor)
8283
this.session = session;
8384
this.accessor = accessor;
8485

85-
stack.Push(new TrackingStackFrame(false));
86+
stack.Push(new TrackingStackFrame());
8687

8788
Subscribe();
8889
}

Extensions/Xtensive.Orm.Tracking/Internals/TrackingItem.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System.Collections.Generic;
99
using System.Diagnostics;
1010
using System.Linq;
11+
using Xtensive.Core;
1112
using Xtensive.Tuples;
1213
using Tuple = Xtensive.Tuples.Tuple;
1314

@@ -36,6 +37,8 @@ public void MergeWith(TrackingItem source)
3637
return;
3738
}
3839

40+
ArgumentNullException.ThrowIfNull(source.RawData);
41+
3942
if (State == TrackingItemState.Created && source.State == TrackingItemState.Changed) {
4043
State = TrackingItemState.Created;
4144
MergeWith(source.RawData.Difference);
@@ -72,11 +75,12 @@ private IReadOnlyList<ChangedValue> CalculateChangedValues()
7275
changedValuesList.Add(new ChangedValue(field, origValue, changedValue));
7376
}
7477

75-
return changedValuesList.AsReadOnly();
78+
return changedValuesList.AsSafeWrapper();
7679
}
7780

7881
private void MergeWith(Tuple difference)
7982
{
83+
ArgumentNullException.ThrowIfNull(RawData);
8084
if (RawData.Difference == null)
8185
RawData.Difference = difference;
8286
else
@@ -92,8 +96,7 @@ public TrackingItem(Key key, TrackingItemState state, DifferentialTuple tuple)
9296
}
9397

9498
Key = key;
95-
if (tuple != null)
96-
RawData = (DifferentialTuple) tuple.Clone();
99+
RawData = tuple?.Clone();
97100
State = state;
98101
}
99102
}

Extensions/Xtensive.Orm.Tracking/Internals/TrackingStackFrame.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace Xtensive.Orm.Tracking
1313
{
1414
internal readonly struct TrackingStackFrame : IEnumerable<TrackingItem>
1515
{
16-
private readonly Dictionary<Key, TrackingItem> items;
16+
private readonly Dictionary<Key, TrackingItem> items = new();
1717

1818
public int Count => items.Count;
1919

@@ -49,11 +49,8 @@ public void MergeWith(TrackingStackFrame source)
4949

5050
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
5151

52-
// parameterless ctor not allowed in C#9
53-
//TODO: remove it after moving to C#10
54-
public TrackingStackFrame(bool _)
52+
public TrackingStackFrame()
5553
{
56-
items = new();
5754
}
5855
}
5956
}

Orm/Xtensive.Orm.Tests.Core/Collections/ExtensionCollectionTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public void CombinedTest()
2929
c.Lock();
3030
AssertEx.Throws<InstanceIsLockedException>(() => c.Set(this));
3131

32-
var cc = (ExtensionCollection) c.Clone();
32+
var cc = c.Clone();
3333
AssertEx.HasSameElements(c, cc);
3434

3535
var o = new object();

Orm/Xtensive.Orm.Tests.Core/Tuples/DifferentialTupleTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public void DifferentialTest()
2929

3030
PopulateData(fieldTypes, t1, d);
3131
AssertAreSame(t1, d);
32-
DifferentialTuple c = (DifferentialTuple)d.Clone();
32+
DifferentialTuple c = d.Clone();
3333
AssertAreSame(d, c);
3434

3535
d.Reset();

Orm/Xtensive.Orm.Tests/Storage/Multinode/StorageNodeManagerTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public void AddAlreadyExistingTest()
6868
nodeConfiguration.SchemaMapping.Add(dbo, Schema1);
6969
_ = Domain.StorageNodeManager.AddNode(nodeConfiguration);
7070

71-
var sameConfig = (NodeConfiguration)nodeConfiguration.Clone();
71+
var sameConfig = nodeConfiguration.Clone();
7272
var result = Domain.StorageNodeManager.AddNode(sameConfig);
7373
Assert.That(result, Is.False);
7474
}

Orm/Xtensive.Orm/Collections/ExtensionCollection.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,8 @@ public override void Lock(bool recursive)
106106
#region ICloneable methods
107107

108108
/// <inheritdoc/>
109-
public object Clone()
110-
{
111-
return new ExtensionCollection(this);
112-
}
109+
public ExtensionCollection Clone() => new(this);
110+
object ICloneable.Clone() => Clone();
113111

114112
#endregion
115113

Orm/Xtensive.Orm/Orm/Configuration/DatabaseConfigurationCollection.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2012 Xtensive LLC.
1+
// Copyright (C) 2012 Xtensive LLC.
22
// All rights reserved.
33
// For conditions of distribution and use, see license.
44
// Created by: Denis Krjuchkov
@@ -27,14 +27,16 @@ public IDatabaseConfigurationFlow Add(string name)
2727
}
2828

2929
/// <inheritdoc />
30-
public object Clone()
30+
public DatabaseConfigurationCollection Clone()
3131
{
3232
var result = new DatabaseConfigurationCollection();
3333
foreach (var alias in this)
3434
result.Add(alias.Clone());
3535
return result;
3636
}
3737

38+
object ICloneable.Clone() => Clone();
39+
3840
/// <inheritdoc/>
3941
public override void Lock(bool recursive)
4042
{

Orm/Xtensive.Orm/Orm/Configuration/DomainConfiguration.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -780,14 +780,14 @@ protected override void CopyFrom(ConfigurationBase source)
780780
connectionInfo = configuration.ConnectionInfo;
781781
defaultSchema = configuration.DefaultSchema;
782782
defaultDatabase = configuration.DefaultDatabase;
783-
types = (DomainTypeRegistry) configuration.Types.Clone();
784-
linqExtensions = (LinqExtensionRegistry) configuration.LinqExtensions.Clone();
785-
namingConvention = (NamingConvention) configuration.NamingConvention.Clone();
783+
types = configuration.Types.Clone();
784+
linqExtensions = configuration.LinqExtensions.Clone();
785+
namingConvention = configuration.NamingConvention.Clone();
786786
keyCacheSize = configuration.KeyCacheSize;
787787
keyGeneratorCacheSize = configuration.KeyGeneratorCacheSize;
788788
queryCacheSize = configuration.QueryCacheSize;
789789
recordSetMappingCacheSize = configuration.RecordSetMappingCacheSize;
790-
sessions = (SessionConfigurationCollection) configuration.Sessions.Clone();
790+
sessions = configuration.Sessions.Clone();
791791
upgradeMode = configuration.UpgradeMode;
792792
foreignKeyMode = configuration.ForeignKeyMode;
793793
serviceContainerType = configuration.ServiceContainerType;
@@ -801,13 +801,13 @@ protected override void CopyFrom(ConfigurationBase source)
801801
multidatabaseKeys = configuration.MultidatabaseKeys;
802802
ensureConnectionIsAlive = configuration.EnsureConnectionIsAlive;
803803
options = configuration.Options;
804-
databases = (DatabaseConfigurationCollection) configuration.Databases.Clone();
805-
mappingRules = (MappingRuleCollection) configuration.MappingRules.Clone();
806-
keyGenerators = (KeyGeneratorConfigurationCollection) configuration.KeyGenerators.Clone();
807-
ignoreRules = (IgnoreRuleCollection) configuration.IgnoreRules.Clone();
804+
databases = configuration.Databases.Clone();
805+
mappingRules = configuration.MappingRules.Clone();
806+
keyGenerators = configuration.KeyGenerators.Clone();
807+
ignoreRules = configuration.IgnoreRules.Clone();
808808
shareStorageSchemaOverNodes = configuration.ShareStorageSchemaOverNodes;
809809
ShareQueryCacheOverNodes = configuration.ShareQueryCacheOverNodes;
810-
versioningConvention = (VersioningConvention) configuration.VersioningConvention.Clone();
810+
versioningConvention = configuration.VersioningConvention.Clone();
811811
preferTypeIdsAsQueryParameters = configuration.PreferTypeIdsAsQueryParameters;
812812
maxNumberOfConditons = configuration.MaxNumberOfConditions;
813813
}

Orm/Xtensive.Orm/Orm/Configuration/DomainTypeRegistry.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ public static bool IsDbConnectionAccessor(Type type)
266266
#region ICloneable members
267267

268268
/// <inheritdoc/>
269-
public override object Clone() => new DomainTypeRegistry(this);
269+
public override DomainTypeRegistry Clone() => new(this);
270270

271271
#endregion
272272

Orm/Xtensive.Orm/Orm/Configuration/IgnoreRuleCollection.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,16 @@ public IIgnoreRuleConstructionFlow IgnoreIndex(string indexName)
5151
}
5252

5353
/// <inheritdoc />
54-
public object Clone()
54+
public IgnoreRuleCollection Clone()
5555
{
5656
var result = new IgnoreRuleCollection();
5757
foreach (var rule in this)
5858
result.Add(rule.Clone());
5959
return result;
6060
}
6161

62+
object ICloneable.Clone() => Clone();
63+
6264
/// <inheritdoc />
6365
public override void Lock(bool recursive)
6466
{

Orm/Xtensive.Orm/Orm/Configuration/KeyGeneratorConfigurationCollection.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2012 Xtensive LLC.
1+
// Copyright (C) 2012 Xtensive LLC.
22
// All rights reserved.
33
// For conditions of distribution and use, see license.
44
// Created by: Denis Krjuchkov
@@ -42,14 +42,15 @@ public IKeyGeneratorConfigurationFlow Add<TKeyType>()
4242
}
4343

4444
/// <inheritdoc/>
45-
public object Clone()
45+
public KeyGeneratorConfigurationCollection Clone()
4646
{
4747
var result = new KeyGeneratorConfigurationCollection();
4848
foreach (var generator in this)
4949
result.Add(generator.Clone());
5050
return result;
5151
}
5252

53+
object ICloneable.Clone() => Clone();
5354
/// <inheritdoc/>
5455
public override void Lock(bool recursive)
5556
{

Orm/Xtensive.Orm/Orm/Configuration/LinqExtensionRegistry.cs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2011 Xtensive LLC.
1+
// Copyright (C) 2011 Xtensive LLC.
22
// All rights reserved.
33
// For conditions of distribution and use, see license.
44
// Created by: Denis Krjuchkov
@@ -78,11 +78,8 @@ IEnumerator IEnumerable.GetEnumerator()
7878
/// Clones this instance.
7979
/// </summary>
8080
/// <returns>Clone of this instance.</returns>
81-
public object Clone()
82-
{
83-
return new LinqExtensionRegistry(this);
84-
}
85-
81+
public LinqExtensionRegistry Clone() => new(this);
82+
object ICloneable.Clone() => Clone();
8683

8784
// Constructors
8885

0 commit comments

Comments
 (0)