diff --git a/BInaryKit-Test/BInaryKit-Test.csproj b/BInaryKit-Test/BInaryKit-Test.csproj
index 916fa9a..4b695a0 100644
--- a/BInaryKit-Test/BInaryKit-Test.csproj
+++ b/BInaryKit-Test/BInaryKit-Test.csproj
@@ -1,13 +1,14 @@
- net10.0
BinaryKit_Test
enable
enable
false
true
BinaryKit-Test
+ 14
+ net10.0
@@ -22,7 +23,7 @@
-
+
\ No newline at end of file
diff --git a/BInaryKit-Test/EndianTest.cs b/BInaryKit-Test/EndianTest.cs
index f9815e9..b31082e 100644
--- a/BInaryKit-Test/EndianTest.cs
+++ b/BInaryKit-Test/EndianTest.cs
@@ -10,14 +10,14 @@ public class EndianTest(ITestOutputHelper output)
public void Read_int()
{
const int value = 1000;
- var expected = BitConverter.IsLittleEndian ? value : System.Buffers.Binary.BinaryPrimitives.ReverseEndianness(value);
+ var expected = BitConverter.IsLittleEndian ? value : BinaryPrimitives.ReverseEndianness(value);
var actual = value;
actual = EndianToolkit.Convert(actual, Endianness.Local, Endianness.Little);
output.WriteLine("expected: " + expected);
output.WriteLine("actual: " + actual);
Assert.Equal(expected, actual);
}
-
+
[Fact]
public unsafe void Read_Struct()
{
@@ -25,10 +25,7 @@ public unsafe void Read_Struct()
var expected = value;
var actual = value;
// to big endian
- if (BitConverter.IsLittleEndian)
- {
- new Span(&expected, sizeof(UnionStruct)).Reverse();
- }
+ if (BitConverter.IsLittleEndian) new Span(&expected, sizeof(UnionStruct)).Reverse();
// to big endian
actual = EndianToolkit.Convert(actual, Endianness.Local, Endianness.Big);
output.WriteLine("expected: " + expected);
@@ -41,7 +38,7 @@ public unsafe void Read_Struct()
[Fact]
public void ReverseManyTest()
{
- Span old = [10,20,30,40,50,60,70,80];
+ Span old = [10, 20, 30, 40, 50, 60, 70, 80];
Span expected = stackalloc int[old.Length];
for (var index = 0; index < old.Length; index++)
{
@@ -50,15 +47,10 @@ public void ReverseManyTest()
}
EndianToolkit.ReverseMany(old);
- for (int i = 0; i < old.Length; i++)
- {
+ for (var i = 0; i < old.Length; i++)
if (old[i] != expected[i])
- {
Assert.Fail();
- }
- }
}
-
#endregion
}
\ No newline at end of file
diff --git a/BInaryKit-Test/StreamExTest.cs b/BInaryKit-Test/StreamExTest.cs
index 518dbb9..8fe44ab 100644
--- a/BInaryKit-Test/StreamExTest.cs
+++ b/BInaryKit-Test/StreamExTest.cs
@@ -7,6 +7,24 @@ namespace BinaryKit_Test;
public class StreamExTest(ITestOutputHelper output)
{
+ #region WriteFrom Tests
+
+ [Fact]
+ public unsafe void Write()
+ {
+ UnionStruct expected = new();
+ UnionStruct value = default;
+ using var stream = new MemoryStream();
+ stream.WriteFrom(expected);
+ stream.Position = 0;
+ stream.GetBuffer().AsSpan(0, sizeof(UnionStruct)).CopyTo(new Span(&expected, sizeof(UnionStruct)));
+ output.WriteLine("left: " + expected);
+ output.WriteLine("right: " + value);
+ Assert.Equal(expected, value);
+ }
+
+ #endregion
+
#region ReadAs Tests
[Fact]
@@ -65,29 +83,12 @@ public unsafe void Read_UnionStruct()
#endregion
- #region WriteFrom Tests
-
- [Fact]
- public unsafe void Write()
- {
- UnionStruct expected = new();
- UnionStruct value = default;
- using var stream = new MemoryStream();
- stream.WriteFrom(expected);
- stream.Position = 0;
- stream.GetBuffer().AsSpan(0, sizeof(UnionStruct)).CopyTo(new Span(&expected, sizeof(UnionStruct)));
- output.WriteLine("left: " + expected);
- output.WriteLine("right: " + value);
- Assert.Equal(expected, value);
- }
- #endregion
-
#region Multiple-Test
[Fact]
public unsafe void MultipleRead()
{
- byte[] ints = [10,20,30,40];
+ byte[] ints = [10, 20, 30, 40];
Span span = stackalloc int[1];
var ptr = (int*)Unsafe.AsPointer(ref MemoryMarshal.GetReference(ints));
var expected = *ptr;
@@ -99,17 +100,16 @@ public unsafe void MultipleRead()
stream.ReadManyAs(span2);
if (span2[0] != *(short*)ptr) Assert.Fail();
if (span2[1] != ((short*)ptr)[1]) Assert.Fail();
- }
-
+ }
+
[Fact]
public void MultipleWrite()
{
- byte[] ints = [10,20,30,40];
+ byte[] ints = [10, 20, 30, 40];
using var stream = new MemoryStream();
stream.WriteManyFrom(ints);
- if (stream.GetBuffer() is not [10,20,30,40,..]) Assert.Fail();
- }
-
+ if (stream.GetBuffer() is not [10, 20, 30, 40, ..]) Assert.Fail();
+ }
#endregion
}
\ No newline at end of file
diff --git a/BInaryKit-Test/UnsafeToolkit/Pin-Test.cs b/BInaryKit-Test/UnsafeToolkit/Pin-Test.cs
new file mode 100644
index 0000000..797689b
--- /dev/null
+++ b/BInaryKit-Test/UnsafeToolkit/Pin-Test.cs
@@ -0,0 +1,69 @@
+using Iks.BinaryToolkit.UnsafeToolkit;
+
+namespace BinaryKit_Test.UnsafeToolkit;
+
+public class PinTest
+{
+ // pin must be not null
+ [Fact]
+ public void NotNullPin()
+ {
+ try
+ {
+ // set a null ref
+ string str = null!;
+ using var pin = str.AsPinned();
+ }
+ // throws is right,null cannot be pinned
+ catch
+ {
+ return;
+ }
+
+ Assert.Fail();
+ }
+
+ [Fact]
+ public void NotUseAfterRelease()
+ {
+ var pin = new object().AsPinned();
+ pin.Dispose();
+ // use after release
+ try
+ {
+ var pinTarget = pin.Target;
+ }
+ catch
+ {
+ return;
+ }
+
+ Assert.Fail();
+ }
+
+ [Fact]
+ public void NotMultipleRelease()
+ {
+ var pin = new object().AsPinned();
+ pin.Dispose();
+ // release again
+ try
+ {
+ pin.Dispose();
+ }
+ catch
+ {
+ return;
+ }
+
+ Assert.Fail();
+ }
+
+ [Fact]
+ public void CopyRelease()
+ {
+ var pin_old = new object().AsPinned();
+ var pin_new = pin_old;
+ pin_new.Dispose();
+ }
+}
\ No newline at end of file
diff --git a/BinaryToolKit.slnx b/BinaryToolKit.slnx
index 7d9d028..988c9e0 100644
--- a/BinaryToolKit.slnx
+++ b/BinaryToolKit.slnx
@@ -1,17 +1,17 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/BinaryToolKit/BinaryStreamToolkit.cs b/BinaryToolKit/BinaryStreamToolkit.cs
index 939d89e..d402c66 100644
--- a/BinaryToolKit/BinaryStreamToolkit.cs
+++ b/BinaryToolKit/BinaryStreamToolkit.cs
@@ -1,5 +1,6 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+using Iks.BinaryToolKit.Message;
namespace Iks.BinaryToolkit;
@@ -62,7 +63,7 @@ allows ref struct
}
///
- /// write an unmanaged type(value) to the stream.
+ /// write an unmanaged type(value) to the stream.
///
/// target type
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -75,9 +76,9 @@ allows ref struct
{
stream.Write(new ReadOnlySpan(&value, sizeof(T)));
}
-
+
///
- /// write an unmanaged type(value) to the stream.
+ /// write an unmanaged type(value) to the stream.
///
/// target type
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -106,7 +107,7 @@ allows ref struct
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe void ReadManyAs(Span targetSpan) where T : unmanaged
{
- fixed(T* ptrT = &MemoryMarshal.GetReference(targetSpan))
+ fixed (T* ptrT = &MemoryMarshal.GetReference(targetSpan))
{
ReadManyAs(stream, ptrT, targetSpan.Length);
}
@@ -154,9 +155,9 @@ allows ref struct
/// target position
public unsafe void WriteManyFrom(ReadOnlySpan values) where T : unmanaged
{
- fixed(T* ptrT = &MemoryMarshal.GetReference(values))
+ fixed (T* ptrT = &MemoryMarshal.GetReference(values))
{
- WriteManyFrom(stream,ptrT, values.Length);
+ WriteManyFrom(stream, ptrT, values.Length);
}
}
diff --git a/BinaryToolKit/BinaryToolKit.csproj b/BinaryToolKit/BinaryToolKit.csproj
index bfc99f9..6f7ff86 100644
--- a/BinaryToolKit/BinaryToolKit.csproj
+++ b/BinaryToolKit/BinaryToolKit.csproj
@@ -27,7 +27,7 @@
TRACE RELEASE
true
true
- bin\PackNuget\BinaryToolKit.xml
+ true
portable
true
snupkg
diff --git a/BinaryToolKit/EndianToolkit.cs b/BinaryToolKit/EndianToolkit.cs
index fd0c302..0d71e00 100644
--- a/BinaryToolKit/EndianToolkit.cs
+++ b/BinaryToolKit/EndianToolkit.cs
@@ -5,7 +5,7 @@
namespace Iks.BinaryToolkit;
///
-/// provides methods to process endianness of unmanaged types,including int,float.
+/// provides methods to process endianness of unmanaged types,including int,float.
///
public static class EndianToolkit
{
@@ -43,7 +43,7 @@ private static unsafe void ReverseNoCheck(void* value, int length)
#region Single
///
- /// reverses the endianness of an unmanaged type(value).
+ /// reverses the endianness of an unmanaged type(value).
///
/// value wait to reverse
/// type you want to reverse
@@ -60,7 +60,7 @@ allows ref struct
}
///
- /// reverses the endianness of an unmanaged type(value).
+ /// reverses the endianness of an unmanaged type(value).
///
/// target position you want to reverse
/// The size of the element that this pointer points to
@@ -72,8 +72,9 @@ public static unsafe void Reverse(void* value, int length)
///
- /// converts the endianness of an unmanaged type(value) from one to another.
- /// it cannot to make sure struct members are all in the same endian.it just reverses byte-endianness of the whole struct.
+ /// converts the endianness of an unmanaged type(value) from one to another.
+ /// it cannot to make sure struct members are all in the same endian.it just reverses byte-endianness of the whole
+ /// struct.
///
/// target value
/// source endian,can use local
@@ -87,10 +88,7 @@ allows ref struct
#endif
{
// differ, reverse
- if (from != to)
- {
- ReverseNoCheck(&value, sizeof(T));
- }
+ if (from != to) ReverseNoCheck(&value, sizeof(T));
return value;
}
@@ -101,7 +99,7 @@ allows ref struct
#region Multiple
///
- /// reverses the endianness of multiple unmanaged type(values).
+ /// reverses the endianness of multiple unmanaged type(values).
///
/// target enumerable wait to reverse
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -114,7 +112,7 @@ public static unsafe void ReverseMany(Span values) where T : unmanaged
}
///
- /// reverses the endianness of multiple unmanaged type(values).
+ /// reverses the endianness of multiple unmanaged type(values).
///
/// target position to reverse endianness
/// The size of the element that this pointer points to
@@ -133,7 +131,7 @@ public static unsafe void ReverseMany(void* target, int elementSize, int element
}
///
- /// converts the endianness of multiple unmanaged type(value) from one to another.
+ /// converts the endianness of multiple unmanaged type(value) from one to another.
///
/// target position to reverse endianness
/// source endian
@@ -148,7 +146,7 @@ public static unsafe void ConvertMany(Span target, Endianness from, Endian
}
///
- /// converts the endianness of multiple unmanaged type(value) from one to another.
+ /// converts the endianness of multiple unmanaged type(value) from one to another.
///
/// target position to reverse endianness
/// The size of the element that this pointer points to
@@ -169,32 +167,39 @@ public static unsafe void ConvertMany(void* target, int elementSize, int element
}
///
-/// endianness type definition
+/// endianness type definition
///
public enum Endianness
{
///
- /// little-endian byte order
+ /// little-endian byte order
///
Little,
///
- /// big-endian byte order
+ /// big-endian byte order
///
Big
}
-/// Extension of ,provide Local
+/// Extension of
+///
+/// ,provide
+/// Local
public static class EndiannessExtension
{
- private static readonly Endianness LocalEndianness =
+ ///
+ /// Same as Local,Just to support C# 13 and less
+ ///
+ public static readonly Endianness LocalEndianness =
BitConverter.IsLittleEndian ? Endianness.Little : Endianness.Big;
+ ///
extension(Endianness obj)
{
///
- /// local machine byte order
- /// same as BitConverter.IsLittleEndian
+ /// local machine byte order
+ /// same as BitConverter.IsLittleEndian
///
public static Endianness Local => LocalEndianness;
}
diff --git a/BinaryToolKit/ErrorMessage.cs b/BinaryToolKit/Message/ErrorMessage.cs
similarity index 86%
rename from BinaryToolKit/ErrorMessage.cs
rename to BinaryToolKit/Message/ErrorMessage.cs
index ae16abe..bc0ece0 100644
--- a/BinaryToolKit/ErrorMessage.cs
+++ b/BinaryToolKit/Message/ErrorMessage.cs
@@ -1,4 +1,4 @@
-namespace Iks.BinaryToolkit;
+namespace Iks.BinaryToolKit.Message;
internal static class ErrorMessage
{
diff --git a/BinaryToolKit/Message/ObsoleteMessage.cs b/BinaryToolKit/Message/ObsoleteMessage.cs
new file mode 100644
index 0000000..caaf0a0
--- /dev/null
+++ b/BinaryToolKit/Message/ObsoleteMessage.cs
@@ -0,0 +1,7 @@
+namespace Iks.BinaryToolKit.Message;
+
+internal static class ObsoleteMessage
+{
+ public const string Use_PinnedGCHandle_From_Standard =
+ "This Wrapper has already been obsoleted.Use standard Type PinnedGCHandle from ` System.Runtime.InteropServices.PinnedGCHandle `";
+}
\ No newline at end of file
diff --git a/BinaryToolKit/UnsafeToolkit/Pin.cs b/BinaryToolKit/UnsafeToolkit/Pin.cs
new file mode 100644
index 0000000..1c54ddc
--- /dev/null
+++ b/BinaryToolKit/UnsafeToolkit/Pin.cs
@@ -0,0 +1,139 @@
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Iks.BinaryToolKit.Message;
+
+namespace Iks.BinaryToolkit.UnsafeToolkit;
+
+///
+/// Generics Supported and Auto-Release of .
+///
+/// An object which you want to pin for sometime
+#if NET10_0_OR_GREATER
+[Obsolete(ObsoleteMessage.Use_PinnedGCHandle_From_Standard, false)]
+#endif
+[DebuggerDisplay("Address = {Address}, Target = {Target}")]
+public struct Pin(TPinned objectNeededPinning) : IDisposable, IEquatable> where TPinned : class
+{
+ private GCHandle _handle =
+ GCHandle.Alloc(objectNeededPinning ?? throw new ArgumentNullException(nameof(objectNeededPinning)),
+ GCHandleType.Pinned);
+
+ ///
+ /// Get pinned object
+ ///
+ public readonly TPinned Target => (TPinned)_handle.Target!;
+
+ ///
+ /// Retrieves the address of object data in a Pinned handle.
+ ///
+ /// the address of the object
+ public readonly IntPtr Address => _handle.AddrOfPinnedObject();
+
+ /// Free the to unpin it
+ public void Dispose()
+ {
+ _handle.Free();
+ }
+
+ #region Wrapper GCHandle
+
+ ///
+ /// Equals As
+ /// Returns an identifier for the current object.
+ ///
+ /// An identifier for the current object
+ public readonly override int GetHashCode()
+ {
+ return _handle.GetHashCode();
+ }
+
+ ///
+ /// Same as GCHandle.Equals.
+ /// Indicates whether the current instance is equal to another instance of the same type.
+ ///
+ /// An instance to compare with this instance.
+ /// true if the current instance is equal to the other instance; otherwise, false.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public readonly bool Equals(Pin other)
+ {
+ return _handle.Equals(other._handle);
+ }
+
+ ///
+ /// Same as GCHandle.Equals.
+ /// Indicates whether the current instance is equal to another instance of the same type.
+ ///
+ /// An instance to compare with this instance.
+ /// true if the current instance is equal to the other instance; otherwise, false.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public readonly bool Equals(GCHandle other)
+ {
+ return _handle.Equals(other);
+ }
+
+ ///
+ /// Same as GCHandle.Equals.
+ /// Indicates whether the current instance is equal to another instance of the same type.
+ ///
+ /// An instance to compare with this instance.
+ /// true if the current instance is equal to the other instance; otherwise, false.
+ public readonly override bool Equals(object? other)
+ {
+ return other is GCHandle obj && _handle.Equals(obj);
+ }
+
+ ///
+ /// Same As
+ ///
+ /// Equals
+ ///
+ ///
+ public static bool operator ==(Pin left, Pin right)
+ {
+ return left.Equals(right);
+ }
+
+ ///
+ /// Same As
+ ///
+ /// Equals
+ ///
+ ///
+ public static bool operator !=(Pin left, Pin right)
+ {
+ return !(left == right);
+ }
+
+ ///
+ /// Display Pin ,including Address and Target.ToString()
+ ///
+ public override string ToString()
+ {
+ return $"Pinned Address = {Address}, Target = {Target}";
+ }
+
+ #endregion
+}
+
+///
+/// Provide Pin extension ,such as PinIt,
+///
+#if NET10_0_OR_GREATER
+[Obsolete(ObsoleteMessage.Use_PinnedGCHandle_From_Standard, false)]
+#endif
+public static class PinExtension
+{
+ ///
+ extension(TPinned obj) where TPinned : class
+ {
+ ///
+ /// Make a Pin<TPinned> from obj
+ ///
+ ///
+ public Pin AsPinned()
+ {
+ return new Pin(obj);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Feature.md b/Feature.md
index 21c3306..26ddebc 100644
--- a/Feature.md
+++ b/Feature.md
@@ -1,33 +1,49 @@
# Finished-Feature
+
+ ### `BinaryStreamToolkit`
- + 用于以泛型的方式读写Stream中的数据
- + 主要行为: Ex:Stream
- + 命名空间: Iks.BinaryToolkit.BinaryStreamToolkit
- + 源码位置: 自己翻
- + `ReadAs`(out与返回值模式两种出参方式)、`WriteFrom`
+ + 用于以泛型的方式读写Stream中的数据
+ + 主要行为: Ex:Stream
+ + 命名空间: Iks.BinaryToolkit.BinaryStreamToolkit
+ + 源码位置: 自己翻
+ + `ReadAs`(out与返回值模式两种出参方式)、`WriteFrom`
+ ### `Multiple-BinaryStreamToolkit`
- + 用于以泛型的方式读取多个数据,提供`指针(T*)`与`Span`支持
- + 主要行为: Ex:Stream
- + 命名空间: Iks.BinaryToolkit.BinaryStreamToolkit
- + 源码位置: 自己翻
- + `ReadManyAs`、`WriteManyFrom`
+ + 用于以泛型的方式读取多个数据,提供`指针(T*)`与`Span`支持
+ + 主要行为: Ex:Stream
+ + 命名空间: Iks.BinaryToolkit.BinaryStreamToolkit
+ + 源码位置: 自己翻
+ + `ReadManyAs`、`WriteManyFrom`
+ ### `EndianToolkit`
- + 用于以泛型的方式反转端序,算是`BinaryPrimitives`的增加与封装
- + 主要行为: static: EndianToolkit
- + 命名空间: Iks.BinaryToolkit.EndianToolkit
- + 源码位置: 自己翻
- + `Convert(value,from,to)`语义明确,支持填写Local: `from Local to Big`
- + 能`allows ref struct`的尽力allow了,如果`ref struct`的内存布局里真有`指针(T*,ref)`不行(*`.NET 8因为不能allow也不行`*)
- + `Reverse` 同样的`指针(T*)`与`Span`出参
+ + 用于以泛型的方式反转端序,算是`BinaryPrimitives`的增加与封装
+ + 主要行为: static: EndianToolkit
+ + 命名空间: Iks.BinaryToolkit.EndianToolkit
+ + 源码位置: 自己翻
+ + `Convert(value,from,to)`语义明确,支持填写Local: `from Local to Big`
+ + 能`allows ref struct`的尽力allow了,如果`ref struct`的内存布局里真有`指针(T*,ref)`不行(
+ *`.NET 8因为不能allow也不行`*)
+ + `Reverse` 同样的`指针(T*)`与`Span`出参
+ ### Multiple-EndianToolkit
- + 用于以泛型的方式反转集合元素端序,与`Multiple-BinaryStreamToolkit`配合使用
- + 主要行为: static: EndianToolkit
- + 命名空间: Iks.BinaryToolkit.EndianToolkit
- + 源码位置: 自己翻
- + `ConvertMany(values,from,to)`同上,针对多个元素不会多次评估是否包含`指针(T*,ref)`
- + `ReverseMany`依旧是`Span`和`指针(T*)`
+ + 用于以泛型的方式反转集合元素端序,与`Multiple-BinaryStreamToolkit`配合使用
+ + 主要行为: static: EndianToolkit
+ + 命名空间: Iks.BinaryToolkit.EndianToolkit
+ + 源码位置: 自己翻
+ + `ConvertMany(values,from,to)`同上,针对多个元素不会多次评估是否包含`指针(T*,ref)`
+ + `ReverseMany`依旧是`Span`和`指针(T*)`
++ ### `Pin` ,A `GCHandle` Wrapper
+ + 为NET10以下版本提供一个带Dispose方法的GCHandle
+ +
+ NET10以上请使用标准库[PinnedGCHandle\](https://learn.microsoft.com/dotnet/api/system.runtime.interopservices.pinnedgchandle-1?view=net-10.0)
+ + 行为与NET10的`PinnedGCHandle`有些不一致,`PinnedGCHandle`类型范围更大,它不检查对象是否是`可Pin`的
+ + 我的实现`Pin`作为`GCHandle`的封装,并不能绕过`GCHandle`的API限制
+ + 主要行为: struct Pin/static PinExtension
+ + 命名空间: Iks.BinaryToolkit.UnsafeToolkit.Pin
+ + 源码位置: 自己翻
+ + 用途: 暂时pin住一个对象,用于与非托管代码交互,主要提供语法简洁性、额外的null检查、using自动释放
+
+> [!CAUTION]
+> Remember To Dispose It!
# Thinking
+
+ ## 还没想好(大声)
+ ### 欢迎贡献
\ No newline at end of file
diff --git a/README.md b/README.md
index 3750c32..141a22e 100644
--- a/README.md
+++ b/README.md
@@ -1,38 +1,45 @@
# Feature:
+
#### [跳转到`Feature`](Feature.md)
# Github-Actions
+
#### 可能我调的`actions`比我的库有用一点(
+
#### [跳转到我的`Actions`](.github/workflows/dotnet-build-publish.yml)
+
+ 只需要为仓库添加`NUGET_API_KEY机密`并修改`env: project`即可使用
+ **通过`打Tag`执行发布流程**
- + `版本号` 就是 `Tag`名
- + `Preview版本`在`Tag`中后缀`preview`
- + 自动生成符号包`snupkg`并推送
- + 您只需要关心`Icon`,`LICENSE`,`ReadMeFile`和`包描述`即可(都是IDE中很好指定的)
+ + `版本号` 就是 `Tag`名
+ + `Preview版本`在`Tag`中后缀`preview`
+ + 自动生成符号包`snupkg`并推送
+ + 您只需要关心`Icon`,`LICENSE`,`ReadMeFile`和`包描述`即可(都是IDE中很好指定的)
+
# 为什么我们需要泛型支持?
-+
+
++
+ `T Stream.ReadAs()`
+ 用于从Stream中读取一个非托管类型数据(如int,Int128)
+ `void Stream.Write(in T)`
+ 用于向Stream中写入一个非托管类型数据(如int,Int128)
+ ### 我们不需要将函数名当泛型使用的函数,请考虑以下场景
+ 如果您需要实现一种二进制格式的数据的读写,如果您使用NET提供的蹩脚`BinaryReader`作为您的辅助
- ```csharp
- class DataReader
- {
- BinaryReader _reader;
- public int ReadInt(){
- return _reader.ReadInt();
- }
- ...
+```csharp
+class DataReader
+{
+ BinaryReader _reader;
+ public int ReadInt(){
+ return _reader.ReadInt();
}
- ```
- 您会发现您被BinaryReader绑架了,要么你自己也各种`ReadInt`,`ReadShort`,要么你就得switch进行类型分发,现在,我替您完成了简单的类型读写操作
+ ...
+}
+```
+您会发现您被BinaryReader绑架了,要么你自己也各种`ReadInt`,`ReadShort`,要么你就得switch进行类型分发,现在,我替您完成了简单的类型读写操作
+ `Iks.Binary.EndianToolkit`理由同上,且有更严重的类型分发问题
- + 如果您采用了泛型,即使您将泛型参数类型限制到`INumber`,您也用不了`BinaryPrimitives`进行读写,如果您不希望使用非安全代码您可能会写出类似下面的东西
+ + 如果您采用了泛型,即使您将泛型参数类型限制到`INumber`,您也用不了`BinaryPrimitives`
+ 进行读写,如果您不希望使用非安全代码您可能会写出类似下面的东西
```csharp
void Usage(T value)
{