Skip to content

Commit 0abfbe3

Browse files
committed
refactor: enhance nullability annotations and improve code safety across multiple files
1 parent 5af5174 commit 0abfbe3

20 files changed

Lines changed: 98 additions & 44 deletions

src/MADE.Collections/Compare/GenericEqualityComparer{T}.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ public GenericEqualityComparer(Func<T, object> comparison)
4343
/// <exception cref="T:System.Exception">The <see cref="Comparison"/> callback throws an exception.</exception>
4444
public bool Equals(T? x, T? y)
4545
{
46+
if (x == null || y == null)
47+
{
48+
return x == null && y == null;
49+
}
50+
4651
object first = this.Comparison.Invoke(x);
4752
object second = this.Comparison.Invoke(y);
4853

src/MADE.Collections/DictionaryExtensions.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public static class DictionaryExtensions
3131
/// </typeparam>
3232
/// <exception cref="T:System.ArgumentNullException">The <paramref name="dictionary"/> or <paramref name="key"/> is <see langword="null"/>.</exception>
3333
public static void AddOrUpdate<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key, TValue value)
34+
where TKey : notnull
3435
{
3536
ArgumentNullException.ThrowIfNull(dictionary);
3637
ArgumentNullException.ThrowIfNull(key);
@@ -52,18 +53,17 @@ public static void AddOrUpdate<TKey, TValue>(this Dictionary<TKey, TValue> dicti
5253
/// <param name="key">The key to get a value for.</param>
5354
/// <param name="defaultValue">The default value to return if not exists. Default, null.</param>
5455
/// <returns>The value if it exists for the key; otherwise, null.</returns>
55-
public static TValue GetValueOrDefault<TKey, TValue>(
56+
public static TValue? GetValueOrDefault<TKey, TValue>(
5657
this Dictionary<TKey, TValue> dictionary,
5758
TKey key,
58-
TValue defaultValue = default)
59+
TValue? defaultValue = default)
60+
where TKey : notnull
5961
{
60-
var result = defaultValue;
61-
62-
if (dictionary != null && dictionary.ContainsKey(key))
62+
if (dictionary != null && dictionary.TryGetValue(key, out var result))
6363
{
64-
result = dictionary[key];
64+
return result;
6565
}
6666

67-
return result;
67+
return defaultValue;
6868
}
6969
}

src/MADE.Collections/ObjectModel/ObservableItemCollection{T}.cs

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -144,13 +144,27 @@ public void RemoveRange(IEnumerable<T> items)
144144
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
145145
/// </summary>
146146
public void Dispose()
147+
{
148+
this.Dispose(true);
149+
GC.SuppressFinalize(this);
150+
}
151+
152+
/// <summary>
153+
/// Releases unmanaged and optionally managed resources.
154+
/// </summary>
155+
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
156+
protected virtual void Dispose(bool disposing)
147157
{
148158
if (this.disposed)
149159
{
150160
return;
151161
}
152162

153-
this.ClearItems();
163+
if (disposing)
164+
{
165+
this.ClearItems();
166+
}
167+
154168
this.disposed = true;
155169
}
156170

@@ -178,11 +192,19 @@ protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
178192
switch (e.Action)
179193
{
180194
case NotifyCollectionChangedAction.Add:
181-
this.RegisterPropertyChangedEvents(e.NewItems);
195+
if (e.NewItems != null)
196+
{
197+
this.RegisterPropertyChangedEvents(e.NewItems);
198+
}
199+
182200
break;
183201
case NotifyCollectionChangedAction.Remove:
184202
case NotifyCollectionChangedAction.Replace:
185-
this.UnregisterPropertyChangedEvents(e.OldItems);
203+
if (e.OldItems != null)
204+
{
205+
this.UnregisterPropertyChangedEvents(e.OldItems);
206+
}
207+
186208
if (e.NewItems != null)
187209
{
188210
this.RegisterPropertyChangedEvents(e.NewItems);
@@ -223,11 +245,11 @@ private void UnregisterPropertyChangedEvents(IEnumerable items)
223245
}
224246
}
225247

226-
private void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e)
248+
private void OnItemPropertyChanged(object? sender, PropertyChangedEventArgs e)
227249
{
228250
this.CheckDisposed();
229251
this.ItemPropertyChanged?.Invoke(
230252
this,
231-
new ObservableItemCollectionPropertyChangedEventArgs(sender, this.IndexOf((T)sender), e));
253+
new ObservableItemCollectionPropertyChangedEventArgs(sender!, this.IndexOf((T)sender!), e));
232254
}
233255
}

src/MADE.Data.Converters/DateTimeToStringValueConverter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public class DateTimeToStringValueConverter : IValueConverter<DateTime, string>
2525
/// </returns>
2626
public string Convert(DateTime value, object? parameter = default)
2727
{
28-
string format = parameter?.ToString();
28+
string? format = parameter?.ToString();
2929
return !string.IsNullOrWhiteSpace(format)
3030
? value.ToString(format, CultureInfo.InvariantCulture)
3131
: value.ToString(CultureInfo.InvariantCulture);

src/MADE.Data.Converters/Extensions/StringExtensions.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public static string Truncate(this string value, int maxLength)
6161
}
6262

6363
const string suffix = "...";
64-
return value.Substring(0, maxLength - suffix.Length) + suffix;
64+
return string.Concat(value.AsSpan(0, maxLength - suffix.Length), suffix);
6565
}
6666

6767
/// <summary>
@@ -96,7 +96,7 @@ public static string ToDefaultCase(this string value)
9696
/// <param name="value">The string value to convert.</param>
9797
/// <param name="encoding">The encoding to get the value bytes while converting.</param>
9898
/// <returns>The Base64 string representing the value.</returns>
99-
public static string ToBase64(this string value, Encoding encoding = default)
99+
public static string ToBase64(this string value, Encoding? encoding = default)
100100
{
101101
encoding ??= Encoding.UTF8;
102102
return Convert.ToBase64String(encoding.GetBytes(value));
@@ -108,7 +108,7 @@ public static string ToBase64(this string value, Encoding encoding = default)
108108
/// <param name="base64Value">The Base64 value to convert.</param>
109109
/// <param name="encoding">The encoding to get the value string while converting.</param>
110110
/// <returns>The string value representing the Base64 string.</returns>
111-
public static string FromBase64(this string base64Value, Encoding encoding = default)
111+
public static string FromBase64(this string base64Value, Encoding? encoding = default)
112112
{
113113
encoding ??= Encoding.UTF8;
114114
return encoding.GetString(Convert.FromBase64String(base64Value));

src/MADE.Data.EFCore/EntityBase{TKey}.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public abstract class EntityBase<TKey> : IEntityBase<TKey>
1616
/// Gets or sets the identifier of the entity.
1717
/// </summary>
1818
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
19-
public TKey Id { get; set; }
19+
public TKey Id { get; set; } = default!;
2020

2121
/// <summary>
2222
/// Gets or sets the date of the entity's creation.

src/MADE.Data.EFCore/Extensions/DbContextExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public static async Task UpdateAsync<T>(
3535
T entity,
3636
CancellationToken cancellationToken = default)
3737
{
38-
context.Update(entity);
38+
context.Update(entity!);
3939
await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
4040
}
4141

src/MADE.Data.Serialization/Json/Converters/JsonTypeMigrationConverter.cs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public class JsonTypeMigrationConverter : JsonConverter<object>
3232
/// To add migrations, call the <see cref="AddTypeMigration"/> method.
3333
/// </remarks>
3434
public JsonTypeMigrationConverter()
35-
: this(null)
35+
: this(Array.Empty<JsonTypeMigration>())
3636
{
3737
}
3838

@@ -42,7 +42,7 @@ public JsonTypeMigrationConverter()
4242
/// <param name="migrations">The type migrations to initialize with.</param>
4343
public JsonTypeMigrationConverter(params JsonTypeMigration[] migrations)
4444
{
45-
if (migrations != null && migrations.Any())
45+
if (migrations != null && migrations.Length > 0)
4646
{
4747
this.migrations.AddRange(migrations);
4848
}
@@ -60,7 +60,7 @@ public void AddTypeMigration(JsonTypeMigration migration)
6060

6161
lock (this.migrationLock)
6262
{
63-
JsonTypeMigration existingMigration = this.migrations.FirstOrDefault(
63+
JsonTypeMigration? existingMigration = this.migrations.FirstOrDefault(
6464
m =>
6565
m.FromAssemblyName == migration.FromAssemblyName &&
6666
m.FromTypeName == migration.FromTypeName);
@@ -85,11 +85,14 @@ public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonS
8585

8686
if (root.ValueKind == JsonValueKind.Object && root.TryGetProperty("$type", out JsonElement typeElement))
8787
{
88-
string typeString = typeElement.GetString();
89-
resolvedType = this.ResolveType(typeString) ?? typeToConvert;
88+
string? typeString = typeElement.GetString();
89+
if (typeString != null)
90+
{
91+
resolvedType = this.ResolveType(typeString) ?? typeToConvert;
92+
}
9093
}
9194

92-
return root.Deserialize(resolvedType, this.GetInnerOptions(options));
95+
return root.Deserialize(resolvedType, this.GetInnerOptions(options))!;
9396
}
9497

9598
/// <inheritdoc/>
@@ -110,13 +113,13 @@ private JsonSerializerOptions GetInnerOptions(JsonSerializerOptions options)
110113
return this.innerOptions;
111114
}
112115

113-
private Type ResolveType(string typeString)
116+
private Type? ResolveType(string typeString)
114117
{
115118
int commaIndex = typeString.IndexOf(',');
116119
string typeName = commaIndex >= 0 ? typeString[..commaIndex].Trim() : typeString.Trim();
117-
string assemblyName = commaIndex >= 0 ? typeString[(commaIndex + 1)..].Trim() : null;
120+
string? assemblyName = commaIndex >= 0 ? typeString[(commaIndex + 1)..].Trim() : null;
118121

119-
JsonTypeMigration migration;
122+
JsonTypeMigration? migration;
120123
lock (this.migrationLock)
121124
{
122125
migration = this.migrations.FirstOrDefault(

src/MADE.Data.Serialization/Json/JsonTypeMigration.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ public class JsonTypeMigration
1818
/// <param name="toType">The type being migrated to.</param>
1919
public JsonTypeMigration(Type fromType, Type toType)
2020
{
21-
this.FromAssemblyName = fromType.Assembly.GetName().Name;
22-
this.FromTypeName = fromType.FullName;
21+
this.FromAssemblyName = fromType.Assembly.GetName().Name ?? string.Empty;
22+
this.FromTypeName = fromType.FullName ?? string.Empty;
2323
this.ToType = toType;
2424
}
2525

src/MADE.Data.Validation/Validators/Base64Validator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public override void Validate(object value)
4848
}
4949
else
5050
{
51-
base.Validate(value);
51+
base.Validate(value!);
5252
}
5353

5454
this.IsDirty = true;

0 commit comments

Comments
 (0)