-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Nullability context and code refactor #11
Conversation
Added #nullable-context:enable to main projects. Added #lang-version:latest to main projects. Updated NuGet packages on the main projects. Refactoring: Added braces to code blocks. Converted to file-scope namespaces. Added nullability modifiers where required Added missing null checks Other minor one-click IDE refactors to bring the code base to be more consistent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doing everything in a single commit like this is a no-go. I can't possibly review these changes.
Doing something like enabling nullability is good.
Completely restyling all the lines in the project has little benefit and is not worth the churn it creates. Even if it were a separate commit I still don't want to bother for various reasons.
Understandable, here is a downgraded version 😊 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All in all there's still more stylistic changes than I'd prefer, but the biggest review task was still the nullables.
<Nullable>enable</Nullable> | ||
<LangVersion>latest</LangVersion> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is indented wrong. Also don't set LangVersion
to latest
, set it to a fixed version.
UnitTests/UnitTests.csproj
Outdated
<Nullable>enable</Nullable> | ||
<LangVersion>latest</LangVersion> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same issues as other csproj.
Lidgren.Network/NetBigInteger.cs
Outdated
if (zVal == null || yAccum == null) | ||
{ | ||
throw new InvalidOperationException("both zVal and yAccum should not be null"); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd just make this an assert instead. It should mute nullability warnings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't mute any warning unfortunately, so I'll add another helper method based on AgumentNullException.ThrowIfNull
.
Lidgren.Network/NetBuffer.cs
Outdated
internal byte[] BufferData => m_data ?? throw new InvalidOperationException($"{nameof(m_data)} is null"); | ||
|
||
internal byte[]? m_data; | ||
internal int m_bitLength; | ||
internal int m_readPosition; | ||
|
||
/// <summary> | ||
/// Gets or sets the internal data buffer | ||
/// </summary> | ||
public byte[] Data | ||
public byte[]? Data |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I can tell, m_data
can only be null if the message is currently pooled. I'd just make Data
throw in that case (as it's kind of an invalid state to be doing stuff with it, you shouldn't have a handle) so it doesn't need to be nullable.
Lidgren.Network/NetClient.cs
Outdated
{ | ||
lock (m_connections) | ||
{ | ||
if (m_connections.Count > 0) | ||
{ | ||
LogWarning("Connect attempt failed; Already connected"); | ||
return null; | ||
throw new InvalidOperationException("Connect attempt failed; Already connected"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure it's a good idea to change behavior like this.
Lidgren.Network/NetUtility.cs
Outdated
public static string MakeCommaDelimitedList<T>(IReadOnlyList<T> list) | ||
{ | ||
var cnt = list.Count; | ||
StringBuilder bdr = new StringBuilder(cnt * 5); // educated guess | ||
for(int i=0;i<cnt;i++) | ||
for (int i = 0; i < cnt; i++) | ||
{ | ||
bdr.Append(list[i].ToString()); | ||
bdr.Append(list[i]?.ToString()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Annotate the function with T : notnull
instead, don't change the behavior.
{ | ||
var defaultAddress = ProbeDefaultRouteAddress(); | ||
IPAddress? defaultAddress = ProbeDefaultRouteAddress(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change shouldn't be necessary.
@@ -71,7 +72,7 @@ private static IPAddress ProbeDefaultRouteAddress() | |||
// This basically gets us the network interface address "that goes to the router". | |||
using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); | |||
socket.Connect(new IPAddress(new byte[] { 1, 1, 1, 1 }), 12345); | |||
return ((IPEndPoint)socket.LocalEndPoint).Address; | |||
return (socket.LocalEndPoint as IPEndPoint)?.Address; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LocalEndPoint
is expected to be set by the connect call, this should be an assert if anything at all.
UnitTests/NetUtilityTests.cs
Outdated
@@ -51,7 +51,7 @@ public void TestResolveEndPointBasic() | |||
var addr = NetUtility.Resolve("example.com", 55555); | |||
|
|||
Assert.That(addr, Is.Not.Null); | |||
Assert.That(addr.Port, Is.EqualTo(55555)); | |||
Assert.That(addr?.Port, Is.EqualTo(55555)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't make sense, the address is null checked right above.
UnitTests/NetUtilityTests.cs
Outdated
@@ -88,7 +88,7 @@ public async Task TestResolveEndPointAsyncBasic() | |||
var addr = await NetUtility.ResolveAsync("example.com", 55555); | |||
|
|||
Assert.That(addr, Is.Not.Null); | |||
Assert.That(addr.Port, Is.EqualTo(55555)); | |||
Assert.That(addr?.Port, Is.EqualTo(55555)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto.
I believe I've worked out all your comments. |
@PJB3005 I believe there is a workflow button to be pressed?.. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll just fix the last couple issues myself.
Lidgren.Network/NetException.cs
Outdated
/// <summary>Returns the passed <paramref name="argument"/>, but throws an <see cref="NetException"/> if the <paramref name="argument"/> is null.</summary> | ||
/// <param name="argument">The reference type argument to validate as non-null.</param> | ||
/// <param name="paramName">The name of the parameter with which <paramref name="argument"/> corresponds.</param> | ||
#if !DEBUG | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static T ThrowIfNull<T>(T argument, string? paramName = null) | ||
{ | ||
return argument; | ||
} | ||
#else | ||
#if NET5_0_OR_GREATER | ||
public static T ThrowIfNull<T>([NotNull] T? argument, [CallerArgumentExpression(nameof(argument))] string? paramName = null) where T : class | ||
#else | ||
public static T ThrowIfNull<T>([NotNull] T? argument, string? paramName = null) where T : class | ||
#endif | ||
{ | ||
return argument ?? throw new NetException($"{paramName ?? "argument"} is null"); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like these methods for a few reasons:
- They should be internal, not public.
- They're used interchangeably as asserts and
ArgumentNullException
s, which is confusing.
Lidgren.Network/NetPeer.Discovery.cs
Outdated
@@ -19,7 +19,7 @@ public void DiscoverLocalPeers(int serverPort) | |||
um.m_messageType = NetMessageType.Discovery; | |||
Interlocked.Increment(ref um.m_recyclingCount); | |||
|
|||
m_unsentUnconnectedMessages.Enqueue(new NetTuple<NetEndPoint, NetOutgoingMessage>(new NetEndPoint(NetUtility.GetBroadcastAddress() ?? throw new InvalidOperationException(), serverPort), um)); | |||
m_unsentUnconnectedMessages.Enqueue(new NetTuple<NetEndPoint, NetOutgoingMessage>(new NetEndPoint(NetException.ThrowIfNull(NetUtility.GetBroadcastAddress()), serverPort), um)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't great because it doesn't further explain why the exception happened.
Lidgren.Network/NetQueue.cs
Outdated
public T?[] ToArray() | ||
{ | ||
m_lock.EnterReadLock(); | ||
try | ||
{ | ||
T[] retval = new T[m_size]; | ||
T?[] retval = new T[m_size]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It shouldn't be possible for the queue to contain null entries within the actual valid range, so these shouldn't be nullable.
Remove NetException.ThrowIfNull in favor of NetException.Assert, ArgumentNullException and InvalidOperationException. NetException.Assert now has [DoesNotReturnIf(false)] on its bool parameter. This makes the C# compiler understand it for NRT analysis.
Because you made this PR from your |
Address review comments.
Merged. A nice touch with the |
Added #nullable-context:enable to main projects.
Added #lang-version:latest to main projects.
Updated NuGet packages on the main projects.
Refactoring:
Added braces to code blocks.
Converted to file-scope namespaces.
Added nullability modifiers where required
Added missing null checks
Other minor one-click IDE refactors to bring the code base to be more consistent.