Skip to content

Fixed null references in multiple methods, added == and != overloads #247

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 67 additions & 20 deletions nanoFramework.CoreLibrary/System/Guid.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ public struct Guid
/// </summary>
public static readonly Guid Empty = new Guid(new byte[16]);

public Guid()
{
_data = new int[4]; // All zeros
}

/// <summary>
/// Initializes a new instance of the <see cref="Guid"/> structure by using the specified integers and bytes.
/// </summary>
Expand Down Expand Up @@ -103,7 +108,7 @@ public Guid(byte[] b)
#pragma warning disable S3928 // Parameter names used into ArgumentException constructors should match an existing one
if (b.Length != 16)
{
throw new ArgumentException();
throw new ArgumentException("Byte array must be 16 bytes long.", nameof(b));
}
#pragma warning restore S3928 // Parameter names used into ArgumentException constructors should match an existing one

Expand Down Expand Up @@ -160,29 +165,28 @@ public Guid(string g)
/// <exception cref="ArgumentException"><paramref name="value"/> is not a <see cref="Guid"/>.</exception>
public int CompareTo(object value)
{
if (value == null)
{
return 1;
}

#pragma warning disable S3928 // Parameter names used into ArgumentException constructors should match an existing one
if (value is not Guid)
{
throw new ArgumentException();
}
#pragma warning restore S3928 // Parameter names used into ArgumentException constructors should match an existing one
if (value == null) return 1;
if (value is not Guid other) throw new ArgumentException("Object must be of type Guid.");

int[] other = ((Guid)value)._data;
other ??= new int[4];
return CompareTo(other);
}

/// <summary>
/// Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object.
/// </summary>
/// <param name="other">An object to compare with this instance.</param>
/// <returns>A value that indicates the relative order of the objects being compared.</returns>
public int CompareTo(Guid other)
{
_data ??= new int[4];
other._data ??= new int[4];
for (int i = 0; i < 4; i++)
{
if (_data[i] != other[i])
if (_data[i] != other._data[i])
{
return _data[i] - other[i];
return _data[i] - other._data[i];
}
}

return 0;
}

Expand All @@ -201,6 +205,8 @@ public int CompareTo(object value)
/// </remarks>
public byte[] ToByteArray()
{
_data ??= new int[4]; // Initialize if null (treat as Empty)

byte[] buffer = new byte[16];

int index = 0;
Expand Down Expand Up @@ -289,10 +295,19 @@ public override bool Equals(object o)
return false;
}

int[] other = ((Guid)o)._data;
other ??= new int[4];
return o is Guid other && Equals(other);
}

return (_data[0] == other[0]) && (_data[1] == other[1]) && (_data[2] == other[2]) && (_data[3] == other[3]);
/// <summary>
/// Indicates whether the current object is equal to another object of the same type.
/// </summary>
/// <param name="other">An object to compare with this object.</param>
/// <returns>true if the current object is equal to the other parameter; otherwise, false.</returns>
public bool Equals(Guid other)
{
_data ??= new int[4];
other._data ??= new int[4];
return (_data[0] == other._data[0]) && (_data[1] == other._data[1]) && (_data[2] == other._data[2]) && (_data[3] == other._data[3]);
}

/// <summary>
Expand All @@ -301,6 +316,7 @@ public override bool Equals(object o)
/// <returns>The hash code for this instance.</returns>
public override int GetHashCode()
{
_data ??= new int[4]; // Initialize if null (treat as Empty)
return _data[0] ^ _data[1] ^ _data[2] ^ _data[3];
}

Expand Down Expand Up @@ -434,6 +450,8 @@ public static bool TryParseGuidWithDashes(
return true;
}



/// <summary>
/// Converts a hex sub-string to a long, while incrementing the parsePos.
/// </summary>
Expand All @@ -447,5 +465,34 @@ private static long HexStringToLong(string str, ref int parsePos, int requiredLe
parsePos += requiredLength;
return result;
}

/// <summary>
/// Determines whether two specified instances of <see cref="Guid"/> are equal.
/// </summary>
/// <param name="a">The first <see cref="Guid"/> to compare.</param>
/// <param name="b">The second <see cref="Guid"/> to compare.</param>
/// <returns><see langword="true"/> if <paramref name="a"/> equals <paramref name="b"/>; otherwise, <see langword="false"/>.</returns>
public static bool operator ==(Guid a, Guid b)
{
// Defensive null handling, though _data should always be initialized
a._data ??= new int[4];
b._data ??= new int[4];

return (a._data[0] == b._data[0]) &&
(a._data[1] == b._data[1]) &&
(a._data[2] == b._data[2]) &&
(a._data[3] == b._data[3]);
}

/// <summary>
/// Determines whether two specified instances of <see cref="Guid"/> are not equal.
/// </summary>
/// <param name="a">The first <see cref="Guid"/> to compare.</param>
/// <param name="b">The second <see cref="Guid"/> to compare.</param>
/// <returns><see langword="true"/> if <paramref name="a"/> does not equal <paramref name="b"/>; otherwise, <see langword="false"/>.</returns>
public static bool operator !=(Guid a, Guid b)
{
return !(a == b);
}
}
}