diff --git a/README.md b/README.md
index 36f6199..e71c4d6 100644
--- a/README.md
+++ b/README.md
@@ -204,7 +204,7 @@ Converts the ULID to a canonical string representation. Format arguments are ign
`==`, `!=`, `<`, `<=`, `>`, `>=`.
- Implements standard comparison and equality methods:\
`CompareTo`, `Equals`, `GetHashCode`.
-- Provides implicit operators to and from `Guid`.
+- Provides implicit operators to and from `Guid` and `string`.
### GenerationOptions
@@ -448,11 +448,11 @@ Job=DefaultJob
| ToGuid | Ulid | 0.7462 ns | 0.0117 ns | - | - |
| ToGuid | NUlid | 0.2691 ns | 0.0070 ns | - | - |
-| ToString | ByteAetherUlid | 12.2227 ns | 0.2543 ns | 0.0096 | 80 B |
-| ToString | NetUlid | 23.7706 ns | 0.2422 ns | 0.0095 | 80 B |
-| ToString | Ulid | 11.1126 ns | 0.2121 ns | 0.0096 | 80 B |
-| ToString | NUlid | 28.9672 ns | 0.1506 ns | 0.0095 | 80 B |
-| ToString | Guid | 7.2446 ns | 0.0341 ns | 0.0115 | 96 B |
+| ToString | ByteAetherUlid | 12.254 ns | 0.2822 ns | 0.0096 | 80 B |
+| ToString | NetUlid | 26.314 ns | 0.2748 ns | 0.0095 | 80 B |
+| ToString | Ulid | 12.373 ns | 0.1887 ns | 0.0096 | 80 B |
+| ToString | NUlid | 27.661 ns | 0.2090 ns | 0.0095 | 80 B |
+| ToString | Guid | 7.208 ns | 0.0447 ns | 0.0115 | 96 B |
| CompareTo | ByteAetherUlid | 0.0007 ns | 0.0022 ns | - | - |
| CompareTo | NetUlid | 3.6812 ns | 0.0298 ns | - | - |
diff --git a/src/ByteAether.Ulid.Tests/Ulid.Comparable.Tests.cs b/src/ByteAether.Ulid.Tests/Ulid.Comparable.Tests.cs
index 715c1a3..a1981df 100644
--- a/src/ByteAether.Ulid.Tests/Ulid.Comparable.Tests.cs
+++ b/src/ByteAether.Ulid.Tests/Ulid.Comparable.Tests.cs
@@ -75,7 +75,7 @@ public void CompareTo_NullUlid_ShouldReturnPositive()
var ulid = Ulid.New();
// Act
- var comparisonResult = ulid.CompareTo(null);
+ var comparisonResult = ulid.CompareTo((object?)null);
// Assert
Assert.True(comparisonResult > 0);
diff --git a/src/ByteAether.Ulid.Tests/Ulid.Equatable.Tests.cs b/src/ByteAether.Ulid.Tests/Ulid.Equatable.Tests.cs
index cecbf27..a652dd8 100644
--- a/src/ByteAether.Ulid.Tests/Ulid.Equatable.Tests.cs
+++ b/src/ByteAether.Ulid.Tests/Ulid.Equatable.Tests.cs
@@ -65,7 +65,7 @@ public void Equals_Null_ShouldReturnFalse()
var ulid = Ulid.New();
// Act & Assert
- Assert.False(ulid.Equals(null));
+ Assert.False(ulid.Equals((object?)null));
}
[Fact]
@@ -89,4 +89,4 @@ public void Equals_SameAsObject_ShouldReturnTrue()
// Act & Assert
Assert.True(ulid1.Equals((object)ulid2));
}
-}
+}
\ No newline at end of file
diff --git a/src/ByteAether.Ulid.Tests/Ulid.String.Tests.cs b/src/ByteAether.Ulid.Tests/Ulid.String.Tests.cs
index 5622a56..615cdb3 100644
--- a/src/ByteAether.Ulid.Tests/Ulid.String.Tests.cs
+++ b/src/ByteAether.Ulid.Tests/Ulid.String.Tests.cs
@@ -3,7 +3,7 @@
namespace ByteAether.Ulid.Tests;
public class UlidStringTests
{
- private static readonly string _goodUlidString = "01F8MECHZX3TBDSZG8P8X7XRMM";
+ private const string _goodUlidString = "01F8MECHZX3TBDSZG8P8X7XRMM";
[Fact]
public void ToString_ShouldReturnExpectedString()
@@ -221,7 +221,7 @@ public void TryParse_ReadOnlySpanByte_InvalidInput_ShouldReturnFalse(string inpu
[Fact]
public void ToString_WrongLetters_ShouldReplaceWithCorrect()
{
- // Crockford's Base32 subtitution test
+ // Crockford's Base32 substitution test
var inputChars = new[] { 'O', 'o', 'I', 'i', 'L', 'l', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z' };
var outputChars = new[] { '0', '0', '1', '1', '1', '1', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'X', 'Y', 'Z' };
@@ -236,4 +236,4 @@ public void ToString_WrongLetters_ShouldReplaceWithCorrect()
Assert.Equal(outputString, resultString);
}
}
-}
+}
\ No newline at end of file
diff --git a/src/ByteAether.Ulid/PACKAGE.md b/src/ByteAether.Ulid/PACKAGE.md
index 1853ea7..be3b843 100644
--- a/src/ByteAether.Ulid/PACKAGE.md
+++ b/src/ByteAether.Ulid/PACKAGE.md
@@ -137,7 +137,7 @@ Create from existing `Guid`.
`==`, `!=`, `<`, `<=`, `>`, `>=`.
- Implements standard comparison and equality methods:\
`CompareTo`, `Equals`, `GetHashCode`.
-- Provides implicit operators to and from `Guid`.
+- Provides implicit operators to and from `Guid` and `string`.
### GenerationOptions
diff --git a/src/ByteAether.Ulid/Ulid.String.cs b/src/ByteAether.Ulid/Ulid.String.cs
index cb7e331..f2d8d43 100644
--- a/src/ByteAether.Ulid/Ulid.String.cs
+++ b/src/ByteAether.Ulid/Ulid.String.cs
@@ -2,9 +2,6 @@
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Text;
-#if !(NETSTANDARD2_1_OR_GREATER || NETCOREAPP)
-using System.Runtime.InteropServices;
-#endif
namespace ByteAether.Ulid;
@@ -82,17 +79,28 @@ public readonly partial struct Ulid
#else
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
- public readonly string ToString(string? format = null, IFormatProvider? formatProvider = null)
+ public readonly string ToString(string? format, IFormatProvider? formatProvider) => ToString();
+
+ ///
+ /// Returns a string representation of the current instance of in its canonical Crockford's Base32 format.'
+ ///
+ /// Crockford's Base32 representation of the ULID
+#if NET5_0_OR_GREATER
+ [SkipLocalsInit]
+#endif
+#if NETCOREAPP3_0_OR_GREATER
+ [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
+#else
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+#endif
+ public override readonly string ToString()
{
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP
return string.Create(UlidStringLength, this, (span, ulid) => ulid.TryFill(span, _base32Chars));
#else
Span span = stackalloc char[UlidStringLength];
TryFill(span, _base32Chars);
- unsafe
- {
- return new string((char*)Unsafe.AsPointer(ref MemoryMarshal.GetReference(span)), 0, UlidStringLength);
- }
+ return span.ToString();
#endif
}
@@ -385,4 +393,28 @@ private bool TryFill(Span span, T[] map)
return true;
}
+
+ ///
+ /// Allows implicit conversion of to .
+ ///
+ ///
+ ///
+#if NETCOREAPP3_0_OR_GREATER
+ [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
+#else
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+#endif
+ public static implicit operator string(Ulid ulid) => ulid.ToString();
+
+ ///
+ /// Allows implicit conversion of to .
+ ///
+ ///
+ ///
+#if NETCOREAPP3_0_OR_GREATER
+ [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
+#else
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+#endif
+ public static implicit operator Ulid(string str) => Parse(str);
}
\ No newline at end of file