diff --git a/Dapper.SqlBuilder/SqlBuilder.cs b/Dapper.SqlBuilder/SqlBuilder.cs index 5726fdc6e..cb45d0582 100644 --- a/Dapper.SqlBuilder/SqlBuilder.cs +++ b/Dapper.SqlBuilder/SqlBuilder.cs @@ -10,7 +10,7 @@ public class SqlBuilder private readonly Dictionary _data = new Dictionary(); private int _seq; - private class Clause + private sealed class Clause { public Clause(string sql, object? parameters, bool isInclusive) { @@ -23,7 +23,7 @@ public Clause(string sql, object? parameters, bool isInclusive) public bool IsInclusive { get; } } - private class Clauses : List + private sealed class Clauses : List { private readonly string _joiner, _prefix, _postfix; @@ -36,11 +36,9 @@ public Clauses(string joiner, string prefix = "", string postfix = "") public string ResolveClauses(DynamicParameters p) { - foreach (var item in this) - { - p.AddDynamicParams(item.Parameters); - } - return this.Any(a => a.IsInclusive) + ForEach(item => p.AddDynamicParams(item.Parameters)); + + return Exists(a => a.IsInclusive) ? _prefix + string.Join(_joiner, this.Where(a => !a.IsInclusive) diff --git a/Dapper/DefaultTypeMap.cs b/Dapper/DefaultTypeMap.cs index 98029741a..c2f691883 100644 --- a/Dapper/DefaultTypeMap.cs +++ b/Dapper/DefaultTypeMap.cs @@ -10,7 +10,7 @@ namespace Dapper /// public sealed class DefaultTypeMap : SqlMapper.ITypeMap { - private readonly List _fields; + private readonly FieldInfo[] _fields; private readonly Type _type; /// @@ -42,7 +42,7 @@ internal static MethodInfo GetPropertySetterOrThrow(PropertyInfo propertyInfo, T BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, Type.DefaultBinder, propertyInfo.PropertyType, - propertyInfo.GetIndexParameters().Select(p => p.ParameterType).ToArray(), + Array.ConvertAll(propertyInfo.GetIndexParameters(), p => p.ParameterType), null)!.GetSetMethod(true); } @@ -54,9 +54,9 @@ internal static List GetSettableProps(Type t) .ToList(); } - internal static List GetSettableFields(Type t) + private static FieldInfo[] GetSettableFields(Type t) { - return t.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).ToList(); + return t.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); } /// @@ -156,20 +156,20 @@ public SqlMapper.IMemberMap GetConstructorParameter(ConstructorInfo constructor, // preference order is: // exact match over underscore match, exact case over wrong case, backing fields over regular fields, match-inc-underscores over match-exc-underscores - var field = _fields.Find(p => string.Equals(p.Name, columnName, StringComparison.Ordinal)) - ?? _fields.Find(p => string.Equals(p.Name, backingFieldName, StringComparison.Ordinal)) - ?? _fields.Find(p => string.Equals(p.Name, columnName, StringComparison.OrdinalIgnoreCase)) - ?? _fields.Find(p => string.Equals(p.Name, backingFieldName, StringComparison.OrdinalIgnoreCase)); + var field = Array.Find(_fields, p => string.Equals(p.Name, columnName, StringComparison.Ordinal)) + ?? Array.Find(_fields, p => string.Equals(p.Name, backingFieldName, StringComparison.Ordinal)) + ?? Array.Find(_fields, p => string.Equals(p.Name, columnName, StringComparison.OrdinalIgnoreCase)) + ?? Array.Find(_fields, p => string.Equals(p.Name, backingFieldName, StringComparison.OrdinalIgnoreCase)); if (field is null && MatchNamesWithUnderscores) { var effectiveColumnName = columnName.Replace("_", ""); backingFieldName = "<" + effectiveColumnName + ">k__BackingField"; - field = _fields.Find(p => string.Equals(p.Name, effectiveColumnName, StringComparison.Ordinal)) - ?? _fields.Find(p => string.Equals(p.Name, backingFieldName, StringComparison.Ordinal)) - ?? _fields.Find(p => string.Equals(p.Name, effectiveColumnName, StringComparison.OrdinalIgnoreCase)) - ?? _fields.Find(p => string.Equals(p.Name, backingFieldName, StringComparison.OrdinalIgnoreCase)); + field = Array.Find(_fields, p => string.Equals(p.Name, effectiveColumnName, StringComparison.Ordinal)) + ?? Array.Find(_fields, p => string.Equals(p.Name, backingFieldName, StringComparison.Ordinal)) + ?? Array.Find(_fields, p => string.Equals(p.Name, effectiveColumnName, StringComparison.OrdinalIgnoreCase)) + ?? Array.Find(_fields, p => string.Equals(p.Name, backingFieldName, StringComparison.OrdinalIgnoreCase)); } if (field is not null) diff --git a/Dapper/DynamicParameters.cs b/Dapper/DynamicParameters.cs index f6708b5ce..1feb4d020 100644 --- a/Dapper/DynamicParameters.cs +++ b/Dapper/DynamicParameters.cs @@ -62,10 +62,7 @@ public void AddDynamicParams(object? param) if (subDynamic.templates is not null) { templates ??= new List(); - foreach (var t in subDynamic.templates) - { - templates.Add(t); - } + templates.AddRange(subDynamic.templates); } } else @@ -212,14 +209,7 @@ protected void AddParameters(IDbCommand command, SqlMapper.Identity identity) } // Now that the parameters are added to the command, let's place our output callbacks - var tmp = outputCallbacks; - if (tmp is not null) - { - foreach (var generator in tmp) - { - generator(); - } - } + outputCallbacks?.ForEach(generator => generator()); } foreach (var param in parameters.Values) diff --git a/Dapper/FeatureSupport.cs b/Dapper/FeatureSupport.cs index 4d7d77e2e..f00c38ed3 100644 --- a/Dapper/FeatureSupport.cs +++ b/Dapper/FeatureSupport.cs @@ -6,7 +6,7 @@ namespace Dapper /// /// Handles variances in features per DBMS /// - internal class FeatureSupport + internal sealed class FeatureSupport { private static readonly FeatureSupport Default = new FeatureSupport(false), diff --git a/Dapper/SqlMapper.CacheInfo.cs b/Dapper/SqlMapper.CacheInfo.cs index d235beb6f..69edc4eea 100644 --- a/Dapper/SqlMapper.CacheInfo.cs +++ b/Dapper/SqlMapper.CacheInfo.cs @@ -7,7 +7,7 @@ namespace Dapper { public static partial class SqlMapper { - private class CacheInfo + private sealed class CacheInfo { public DeserializerState Deserializer { get; set; } public Func[]? OtherDeserializers { get; set; } diff --git a/Dapper/SqlMapper.DontMap.cs b/Dapper/SqlMapper.DontMap.cs index a97c5811e..765c7b937 100644 --- a/Dapper/SqlMapper.DontMap.cs +++ b/Dapper/SqlMapper.DontMap.cs @@ -5,6 +5,6 @@ public static partial class SqlMapper /// /// Dummy type for excluding from multi-map /// - private class DontMap { /* hiding constructor */ } + private sealed class DontMap { /* hiding constructor */ } } } diff --git a/Dapper/SqlMapper.Link.cs b/Dapper/SqlMapper.Link.cs index 92b434881..710714412 100644 --- a/Dapper/SqlMapper.Link.cs +++ b/Dapper/SqlMapper.Link.cs @@ -12,7 +12,7 @@ public static partial class SqlMapper /// /// The type to cache. /// The value type of the cache. - internal class Link where TKey : class + internal sealed class Link where TKey : class { public static void Clear(ref Link? head) => Interlocked.Exchange(ref head, null); public static bool TryGet(Link? link, TKey key, [NotNullWhen(true)] out TValue? value) diff --git a/Dapper/SqlMapper.TypeDeserializerCache.cs b/Dapper/SqlMapper.TypeDeserializerCache.cs index 2c2f646db..3a34cd292 100644 --- a/Dapper/SqlMapper.TypeDeserializerCache.cs +++ b/Dapper/SqlMapper.TypeDeserializerCache.cs @@ -8,7 +8,7 @@ namespace Dapper { public static partial class SqlMapper { - private class TypeDeserializerCache + private sealed class TypeDeserializerCache { private TypeDeserializerCache(Type type) { diff --git a/Dapper/SqlMapper.cs b/Dapper/SqlMapper.cs index d23e949a5..a7f2066d8 100644 --- a/Dapper/SqlMapper.cs +++ b/Dapper/SqlMapper.cs @@ -29,7 +29,7 @@ namespace Dapper /// public static partial class SqlMapper { - private class PropertyInfoByNameComparer : IComparer + private sealed class PropertyInfoByNameComparer : IComparer { public int Compare(PropertyInfo? x, PropertyInfo? y) => string.CompareOrdinal(x?.Name, y?.Name); } @@ -3530,9 +3530,9 @@ private static void GenerateDeserializerFromMap(Type type, DbDataReader reader, il.Emit(OpCodes.Ldloc, returnValueLocal); // [target] } - var members = (specializedConstructor is not null - ? names.Select(n => typeMap.GetConstructorParameter(specializedConstructor, n)) - : names.Select(n => typeMap.GetMember(n))).ToList(); + var members = Array.ConvertAll(names, specializedConstructor is not null + ? n => typeMap.GetConstructorParameter(specializedConstructor, n) + : n => typeMap.GetMember(n)); // stack is now [target] bool first = true; diff --git a/benchmarks/Dapper.Tests.Performance/Massive/Massive.cs b/benchmarks/Dapper.Tests.Performance/Massive/Massive.cs index f452a95cb..f4c1c8192 100644 --- a/benchmarks/Dapper.Tests.Performance/Massive/Massive.cs +++ b/benchmarks/Dapper.Tests.Performance/Massive/Massive.cs @@ -322,7 +322,6 @@ public virtual DbCommand CreateUpdateCommand(object o, object key) var settings = (IDictionary)expando; var sbKeys = new StringBuilder(); const string stub = "UPDATE {0} SET {1} WHERE {2} = @{3}"; - var args = new List(); var result = CreateCommand(stub, null); int counter = 0; foreach (var item in settings) diff --git a/benchmarks/Dapper.Tests.Performance/PetaPoco/PetaPoco.cs b/benchmarks/Dapper.Tests.Performance/PetaPoco/PetaPoco.cs index add3df772..2ffa3887c 100644 --- a/benchmarks/Dapper.Tests.Performance/PetaPoco/PetaPoco.cs +++ b/benchmarks/Dapper.Tests.Performance/PetaPoco/PetaPoco.cs @@ -1020,10 +1020,9 @@ public string LastCommand { get { - var sb = new StringBuilder(); if (_lastSql == null) return ""; - sb.Append(_lastSql); + var sb = new StringBuilder(_lastSql); if (_lastArgs != null) { sb.Append("\r\n\r\n"); @@ -1038,14 +1037,14 @@ public string LastCommand public static IMapper Mapper { get; set; } - internal class PocoColumn + internal sealed class PocoColumn { public string ColumnName; public PropertyInfo PropertyInfo; public bool ResultColumn; } - internal class PocoData + internal sealed class PocoData { public static PocoData ForType(Type t) { @@ -1272,7 +1271,7 @@ public Func GetFactory(string key, bool ForceDateTimesToUtc, // ShareableConnection represents either a shared connection used by a transaction, // or a one-off connection if not in a transaction. // Non-shared connections are disposed - private class ShareableConnection : IDisposable + private sealed class ShareableConnection : IDisposable { public ShareableConnection(Database db) {