Skip to content

Commit ea8b8ce

Browse files
committed
Enable nullable reference types, modernize code
1 parent e7cd91b commit ea8b8ce

11 files changed

Lines changed: 146 additions & 134 deletions

Src/Configuration.cs

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ namespace SharpConfig
2121
/// </summary>
2222
public class Configuration : IEnumerable<Section>
2323
{
24-
private static CultureInfo s_cultureInfo;
24+
private static CultureInfo? s_cultureInfo;
2525
private static char s_preferredCommentChar;
2626
private static char s_arrayElementSeparator;
2727
private static readonly Dictionary<Type, ITypeStringConverter> s_typeStringConverters;
@@ -120,8 +120,13 @@ public Section Add(string sectionName)
120120
/// empty.</exception>
121121
public bool Remove(string sectionName)
122122
{
123-
return string.IsNullOrEmpty(sectionName) ? throw new ArgumentNullException(nameof(sectionName))
124-
: Remove(FindSection(sectionName));
123+
if (string.IsNullOrEmpty(sectionName))
124+
{
125+
throw new ArgumentNullException(nameof(sectionName));
126+
}
127+
128+
var section = FindSection(sectionName);
129+
return section != null && Remove(section);
125130
}
126131

127132
/// <summary>
@@ -228,6 +233,11 @@ public static void RegisterTypeStringConverter(ITypeStringConverter converter)
228233

229234
var type = converter.ConvertibleType;
230235

236+
if (type == null)
237+
{
238+
throw new ArgumentException("The converter's ConvertibleType cannot be null.", nameof(converter));
239+
}
240+
231241
if (s_typeStringConverters.ContainsKey(type))
232242
{
233243
throw new InvalidOperationException($"A converter for type '{type.FullName}' is already registered.");
@@ -277,7 +287,7 @@ public static ITypeStringConverter FindTypeStringConverter(Type type)
277287
type = typeof(Enum);
278288
}
279289

280-
if (!s_typeStringConverters.TryGetValue(type, out ITypeStringConverter converter))
290+
if (!s_typeStringConverters.TryGetValue(type, out ITypeStringConverter? converter))
281291
{
282292
converter = FallbackConverter;
283293
}
@@ -302,7 +312,7 @@ public static ITypeStringConverter FindTypeStringConverter(Type type)
302312
/// <exception cref="ArgumentNullException">When <paramref name="filename"/> is null or empty.</exception>
303313
/// <exception cref="FileNotFoundException">When the specified configuration file is not
304314
/// found.</exception>
305-
public static Configuration LoadFromFile(string filename, Encoding encoding = null)
315+
public static Configuration LoadFromFile(string filename, Encoding? encoding = null)
306316
{
307317
if (string.IsNullOrEmpty(filename))
308318
{
@@ -331,7 +341,7 @@ public static Configuration LoadFromFile(string filename, Encoding encoding = nu
331341
/// </returns>
332342
///
333343
/// <exception cref="ArgumentNullException">When <paramref name="stream"/> is null.</exception>
334-
public static Configuration LoadFromStream(Stream stream, Encoding encoding = null)
344+
public static Configuration LoadFromStream(Stream stream, Encoding? encoding = null)
335345
{
336346
if (stream == null)
337347
{
@@ -374,7 +384,7 @@ public static Configuration LoadFromString(string source)
374384
/// </returns>
375385
///
376386
/// <exception cref="ArgumentNullException">When <paramref name="filename"/> is null or empty.</exception>
377-
public static Configuration LoadFromBinaryFile(string filename, BinaryReader reader = null)
387+
public static Configuration LoadFromBinaryFile(string filename, BinaryReader? reader = null)
378388
{
379389
if (string.IsNullOrEmpty(filename))
380390
{
@@ -400,7 +410,7 @@ public static Configuration LoadFromBinaryFile(string filename, BinaryReader rea
400410
/// </returns>
401411
///
402412
/// <exception cref="ArgumentNullException">When <paramref name="stream"/> is null.</exception>
403-
public static Configuration LoadFromBinaryStream(Stream stream, BinaryReader reader = null)
413+
public static Configuration LoadFromBinaryStream(Stream stream, BinaryReader? reader = null)
404414
{
405415
return stream == null ? throw new ArgumentNullException(nameof(stream))
406416
: ConfigurationReader.ReadFromBinaryStream(stream, reader);
@@ -411,7 +421,7 @@ public static Configuration LoadFromBinaryStream(Stream stream, BinaryReader rea
411421
/// </summary>
412422
///
413423
/// <param name="filename">The location of the configuration file.</param>
414-
public void SaveToFile(string filename) => SaveToFile(filename, null);
424+
public void SaveToFile(string filename) => SaveToFile(filename, (Encoding?)null);
415425

416426
/// <summary>
417427
/// Saves the configuration to a file.
@@ -422,7 +432,7 @@ public static Configuration LoadFromBinaryStream(Stream stream, BinaryReader rea
422432
/// is UTF8.</param>
423433
///
424434
/// <exception cref="ArgumentNullException">When <paramref name="filename"/> is null or empty.</exception>
425-
public void SaveToFile(string filename, Encoding encoding)
435+
public void SaveToFile(string filename, Encoding? encoding)
426436
{
427437
if (string.IsNullOrEmpty(filename))
428438
{
@@ -440,7 +450,7 @@ public void SaveToFile(string filename, Encoding encoding)
440450
/// </summary>
441451
///
442452
/// <param name="stream">The stream to save the configuration to.</param>
443-
public void SaveToStream(Stream stream) => SaveToStream(stream, null);
453+
public void SaveToStream(Stream stream) => SaveToStream(stream, (Encoding?)null);
444454

445455
/// <summary>
446456
/// Saves the configuration to a stream.
@@ -451,7 +461,7 @@ public void SaveToFile(string filename, Encoding encoding)
451461
/// is UTF8.</param>
452462
///
453463
/// <exception cref="ArgumentNullException">When <paramref name="stream"/> is null.</exception>
454-
public void SaveToStream(Stream stream, Encoding encoding)
464+
public void SaveToStream(Stream stream, Encoding? encoding)
455465
{
456466
if (stream == null)
457467
{
@@ -466,7 +476,7 @@ public void SaveToStream(Stream stream, Encoding encoding)
466476
/// </summary>
467477
///
468478
/// <param name="filename">The location of the configuration file.</param>
469-
public void SaveToBinaryFile(string filename) => SaveToBinaryFile(filename, null);
479+
public void SaveToBinaryFile(string filename) => SaveToBinaryFile(filename, (BinaryWriter?)null);
470480

471481
/// <summary>
472482
/// Saves the configuration to a binary file, using a specific <see cref="BinaryWriter"/>.
@@ -476,7 +486,7 @@ public void SaveToStream(Stream stream, Encoding encoding)
476486
/// <param name="writer"> The writer to use. Specify null to use the default writer.</param>
477487
///
478488
/// <exception cref="ArgumentNullException">When <paramref name="filename"/> is null or empty.</exception>
479-
public void SaveToBinaryFile(string filename, BinaryWriter writer)
489+
public void SaveToBinaryFile(string filename, BinaryWriter? writer)
480490
{
481491
if (string.IsNullOrEmpty(filename))
482492
{
@@ -494,7 +504,7 @@ public void SaveToBinaryFile(string filename, BinaryWriter writer)
494504
/// </summary>
495505
///
496506
/// <param name="stream">The stream to save the configuration to.</param>
497-
public void SaveToBinaryStream(Stream stream) => SaveToBinaryStream(stream, null);
507+
public void SaveToBinaryStream(Stream stream) => SaveToBinaryStream(stream, (BinaryWriter?)null);
498508

499509
/// <summary>
500510
/// Saves the configuration to a binary file, using a specific <see cref="BinaryWriter"/>.
@@ -504,7 +514,7 @@ public void SaveToBinaryFile(string filename, BinaryWriter writer)
504514
/// <param name="writer">The writer to use. Specify null to use the default writer.</param>
505515
///
506516
/// <exception cref="ArgumentNullException">When <paramref name="stream"/> is null.</exception>
507-
public void SaveToBinaryStream(Stream stream, BinaryWriter writer)
517+
public void SaveToBinaryStream(Stream stream, BinaryWriter? writer)
508518
{
509519
if (stream == null)
510520
{
@@ -580,15 +590,15 @@ void WriteSection(Section section)
580590
/// <exception cref="ArgumentNullException">When a null reference is set.</exception>
581591
public static CultureInfo CultureInfo
582592
{
583-
get => s_cultureInfo;
593+
get => s_cultureInfo!;
584594
set => s_cultureInfo = value ?? throw new ArgumentNullException(nameof(value));
585595
}
586596

587597
/// <summary>
588598
/// Gets the array that contains all valid comment delimiting characters.
589599
/// The default value is { '#', ';' }.
590600
/// </summary>
591-
public static HashSet<char> ValidCommentChars { get; private set; }
601+
public static HashSet<char> ValidCommentChars { get; private set; } = null!;
592602

593603
/// <summary>
594604
/// Gets or sets the preferred comment char when saving configurations.
@@ -603,7 +613,7 @@ public static char PreferredCommentChar
603613
{
604614
if (!ValidCommentChars.Contains(value))
605615
{
606-
throw new ArgumentException("The specified char '" + value + "' is not allowed as a comment char.");
616+
throw new ArgumentException($"The specified char '{value}' is not allowed as a comment char.");
607617
}
608618

609619
s_preferredCommentChar = value;
@@ -749,7 +759,7 @@ public IEnumerable<Section> GetSectionsNamed(string name)
749759
}
750760

751761
// Finds a section by its name.
752-
private Section FindSection(string name)
762+
private Section? FindSection(string name)
753763
{
754764
return _sections.FirstOrDefault(
755765
section => string.Equals(section.Name, name, StringComparison.OrdinalIgnoreCase));

Src/ConfigurationElement.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,12 @@ internal ConfigurationElement(string name)
3232
/// <summary>
3333
/// Gets or sets the comment of this element.
3434
/// </summary>
35-
public string Comment { get; set; }
35+
public string? Comment { get; set; }
3636

3737
/// <summary>
3838
/// Gets the comment above this element.
3939
/// </summary>
40-
public string PreComment { get; set; }
40+
public string? PreComment { get; set; }
4141

4242
/// <summary>
4343
/// Gets the string representation of the element.
@@ -74,9 +74,9 @@ public override string ToString()
7474
private string GetFormattedComment()
7575
{
7676
// Only get the first line of the inline comment.
77-
var comment = Comment;
77+
var comment = Comment!;
7878

79-
var newLineIndex = Comment.IndexOfAny(Environment.NewLine.ToCharArray());
79+
var newLineIndex = comment.IndexOfAny(Environment.NewLine.ToCharArray());
8080
if (newLineIndex >= 0)
8181
{
8282
comment = comment.Substring(0, newLineIndex);
@@ -89,7 +89,7 @@ private string GetFormattedComment()
8989
// to be written to a config file.
9090
private string GetFormattedPreComment()
9191
{
92-
var lines = PreComment.Split(formattedPreCommentSeparator, StringSplitOptions.None);
92+
var lines = PreComment!.Split(formattedPreCommentSeparator, StringSplitOptions.None);
9393

9494
return string.Join(
9595
Environment.NewLine, Array.ConvertAll(lines, s => Configuration.PreferredCommentChar + " " + s));

Src/ConfigurationReader.cs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ private static void Parse(StringReader reader, Configuration config)
2626
var currentSection = new Section(Section.DefaultSectionName);
2727
var preCommentBuilder = new StringBuilder();
2828
var lineNumber = 0;
29-
string line;
29+
string? line;
3030

3131
// Read until EOF.
3232
while ((line = reader.ReadLine()) != null)
@@ -82,7 +82,7 @@ private static void Parse(StringReader reader, Configuration config)
8282
currentSection.PreComment =
8383
preCommentBuilder.ToString().TrimEnd(Environment.NewLine.ToCharArray());
8484

85-
preCommentBuilder.Length = 0; // Clear the SB - With .NET >= 4.0: preCommentBuilder.Clear()
85+
preCommentBuilder.Clear();
8686
}
8787

8888
config._sections.Add(currentSection);
@@ -109,7 +109,7 @@ private static void Parse(StringReader reader, Configuration config)
109109
}
110110
}
111111

112-
private static string ParseComment(string line, out int commentCharIndex)
112+
private static string? ParseComment(string line, out int commentCharIndex)
113113
{
114114
// A comment starts with a valid comment character that:
115115
// 1. is not within a quote (eg. "this is # not a comment"), and
@@ -118,7 +118,7 @@ private static string ParseComment(string line, out int commentCharIndex)
118118
// A quote has two quotation marks, neither of which is escaped.
119119
// For example: "this is a quote \" with an escaped quotation mark inside of it"
120120

121-
string comment = null;
121+
string? comment = null;
122122
commentCharIndex = -1;
123123

124124
var index = 0;
@@ -191,7 +191,7 @@ private static Setting ParseSetting(string line, StringReader reader, ref int li
191191
// 2) "<name>" = <value>
192192
// <name> may contain any char, including '='
193193

194-
string settingName = null;
194+
string? settingName = null;
195195
int equalSignIndex;
196196

197197
// Parse the name first.
@@ -247,18 +247,19 @@ private static Setting ParseSetting(string line, StringReader reader, ref int li
247247
settingValueBuffer.AppendLine("[[");
248248

249249
bool foundClosing = false;
250+
string? multilineLine;
250251

251-
while ((line = reader.ReadLine()) != null)
252+
while ((multilineLine = reader.ReadLine()) != null)
252253
{
253254
++lineNumber;
254255

255-
if (line == "]]")
256+
if (multilineLine == "]]")
256257
{
257258
foundClosing = true;
258259
break;
259260
}
260261

261-
settingValueBuffer.AppendLine(line);
262+
settingValueBuffer.AppendLine(multilineLine);
262263
}
263264

264265
if (!foundClosing)
@@ -271,10 +272,10 @@ private static Setting ParseSetting(string line, StringReader reader, ref int li
271272
settingValue = settingValueBuffer.ToString();
272273
}
273274

274-
return new Setting(settingName, settingValue);
275+
return new Setting(settingName!, settingValue);
275276
}
276277

277-
internal static Configuration ReadFromBinaryStream(Stream stream, BinaryReader reader)
278+
internal static Configuration ReadFromBinaryStream(Stream stream, BinaryReader? reader)
278279
{
279280
if (stream == null)
280281
{

Src/ConfigurationWriter.cs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,21 @@ protected override void Dispose(bool disposing)
2828
}
2929
}
3030

31-
internal static void WriteToStreamTextual(Configuration cfg, Stream stream, Encoding encoding)
31+
internal static void WriteToStreamTextual(Configuration cfg, Stream stream, Encoding? encoding)
3232
{
33-
Debug.Assert(cfg != null);
33+
if (cfg == null)
34+
{
35+
throw new ArgumentNullException(nameof(cfg));
36+
}
3437

3538
if (stream == null)
3639
{
3740
throw new ArgumentNullException(nameof(stream));
3841
}
3942

40-
if (encoding == null)
41-
{
42-
encoding = Encoding.UTF8;
43-
}
43+
encoding ??= Encoding.UTF8;
4444

45-
var str = cfg.SaveToString();
45+
string str = cfg.SaveToString();
4646

4747
// Encode & write the string.
4848
var byteBuffer = new byte[encoding.GetByteCount(str)];
@@ -52,9 +52,12 @@ internal static void WriteToStreamTextual(Configuration cfg, Stream stream, Enco
5252
stream.Flush();
5353
}
5454

55-
internal static void WriteToStreamBinary(Configuration cfg, Stream stream, BinaryWriter writer)
55+
internal static void WriteToStreamBinary(Configuration cfg, Stream stream, BinaryWriter? writer)
5656
{
57-
Debug.Assert(cfg != null);
57+
if (cfg == null)
58+
{
59+
throw new ArgumentNullException(nameof(cfg));
60+
}
5861

5962
if (stream == null)
6063
{

Src/ITypeStringConverter.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public interface ITypeStringConverter
2121
/// <summary>
2222
/// The type that this converter is able to convert to and from a string.
2323
/// </summary>
24-
Type ConvertibleType { get; }
24+
Type? ConvertibleType { get; }
2525

2626
/// <summary>
2727
/// Tries to convert a string value to an object of this converter's type.
@@ -34,7 +34,7 @@ public interface ITypeStringConverter
3434
/// This parameter can be safely ignored for custom converters.
3535
/// </param>
3636
/// <returns>The converted object, or null if conversion is not possible.</returns>
37-
object TryConvertFromString(string value, Type hint);
37+
object? TryConvertFromString(string value, Type hint);
3838
}
3939

4040
/// <summary>
@@ -67,6 +67,6 @@ public abstract class TypeStringConverter<T> : ITypeStringConverter
6767
/// This parameter can be safely ignored for custom converters.
6868
/// </param>
6969
/// <returns>The converted object, or null if conversion is not possible.</returns>
70-
public abstract object TryConvertFromString(string value, Type hint);
70+
public abstract object? TryConvertFromString(string value, Type hint);
7171
}
7272
}

0 commit comments

Comments
 (0)