public static System.Collections.Generic.IEnumerable<T> Where<T>(this System.Collections.Immutable.ImmutableArray<T> immutableArray, System.Func<T, bool> predicate) { throw null; }
}
}
+namespace System.Runtime.InteropServices
+{
+ public static partial class ImmutableCollectionsMarshal
+ {
+ public static System.Collections.Immutable.ImmutableArray<T> AsImmutableArray<T>(T[]? array) { throw null; }
+ public static T[]? AsArray<T>(System.Collections.Immutable.ImmutableArray<T> array) { throw null; }
+ }
+}
<Compile Include="System\Collections\Frozen\FrozenHashTable.cs" />
<Compile Include="System\Collections\Frozen\FrozenSet.cs" />
<Compile Include="System\Collections\Frozen\FrozenSetInternalBase.cs" />
- <Compile Include="System\Collections\Frozen\ImmutableArrayFactory.cs" />
<Compile Include="System\Collections\Frozen\ItemsFrozenSet.cs" />
<Compile Include="System\Collections\Frozen\KeysAndValuesFrozenDictionary.cs" />
<Compile Include="System\Collections\Frozen\SmallFrozenDictionary.cs" />
<Compile Include="System\Collections\Immutable\SortedInt32KeyNode.cs" />
<Compile Include="System\Collections\Immutable\SortedInt32KeyNode.Enumerator.cs" />
<Compile Include="System\Linq\ImmutableArrayExtensions.cs" />
+ <Compile Include="System\Runtime.InteropServices\ImmutableCollectionsMarshal.cs" />
<Compile Include="Validation\Requires.cs" />
<Compile Include="$(CommonPath)System\Runtime\Versioning\NonVersionableAttribute.cs" Link="Common\System\Runtime\Versioning\NonVersionableAttribute.cs" />
<None Include="Interfaces.cd" />
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
namespace System.Collections.Frozen
{
/// <remarks>
/// The order of the keys in the dictionary is unspecified, but it is the same order as the associated values returned by the <see cref="Values"/> property.
/// </remarks>
- public ImmutableArray<TKey> Keys => ImmutableArrayFactory.Create(KeysCore);
+ public ImmutableArray<TKey> Keys => ImmutableCollectionsMarshal.AsImmutableArray(KeysCore);
/// <inheritdoc cref="Keys" />
private protected abstract TKey[] KeysCore { get; }
/// <remarks>
/// The order of the values in the dictionary is unspecified, but it is the same order as the associated keys returned by the <see cref="Keys"/> property.
/// </remarks>
- public ImmutableArray<TValue> Values => ImmutableArrayFactory.Create(ValuesCore);
+ public ImmutableArray<TValue> Values => ImmutableCollectionsMarshal.AsImmutableArray(ValuesCore);
/// <inheritdoc cref="Values" />
private protected abstract TValue[] ValuesCore { get; }
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Numerics;
+using System.Runtime.InteropServices;
namespace System.Collections.Frozen
{
/// <summary>Gets a collection containing the values in the set.</summary>
/// <remarks>The order of the values in the set is unspecified.</remarks>
- public ImmutableArray<T> Items => ImmutableArrayFactory.Create(ItemsCore);
+ public ImmutableArray<T> Items => ImmutableCollectionsMarshal.AsImmutableArray(ItemsCore);
/// <inheritdoc cref="Items" />
private protected abstract T[] ItemsCore { get; }
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Collections.Immutable;
-
-namespace System.Collections.Frozen
-{
- /// <summary>
- /// Stubs to isolate the frozen collection code from the internal details of ImmutableArray
- /// </summary>
- /// <remarks>
- /// This is intended to make it easier to use the frozen collections in environments/conditions
- /// when only the public API of ImmutableArray is available.
- /// </remarks>
- internal static class ImmutableArrayFactory
- {
- public static ImmutableArray<T> Create<T>(T[] array) => new ImmutableArray<T>(array);
- }
-}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections.Immutable;
+
+namespace System.Runtime.InteropServices
+{
+ /// <summary>
+ /// An unsafe class that provides a set of methods to access the underlying data representations of immutable collections.
+ /// </summary>
+ public static class ImmutableCollectionsMarshal
+ {
+ /// <summary>
+ /// Gets an <see cref="ImmutableArray{T}"/> value wrapping the input <typeparamref name="T"/> array.
+ /// </summary>
+ /// <typeparam name="T">The type of elements in the input array.</typeparam>
+ /// <param name="array">The input array to wrap in the returned <see cref="ImmutableArray{T}"/> value.</param>
+ /// <returns>An <see cref="ImmutableArray{T}"/> value wrapping <paramref name="array"/>.</returns>
+ /// <remarks>
+ /// <para>
+ /// When using this method, callers should take extra care to ensure that they're the sole owners of the input
+ /// array, and that it won't be modified once the returned <see cref="ImmutableArray{T}"/> value starts being
+ /// used. Doing so might cause undefined behavior in code paths which don't expect the contents of a given
+ /// <see cref="ImmutableArray{T}"/> values to change after its creation.
+ /// </para>
+ /// <para>
+ /// If <paramref name="array"/> is <see langword="null"/>, the returned <see cref="ImmutableArray{T}"/> value
+ /// will be uninitialized (ie. its <see cref="ImmutableArray{T}.IsDefault"/> property will be <see langword="true"/>).
+ /// </para>
+ /// </remarks>
+ public static ImmutableArray<T> AsImmutableArray<T>(T[]? array)
+ {
+ return new(array);
+ }
+
+ /// <summary>
+ /// Gets the underlying <typeparamref name="T"/> array for an input <see cref="ImmutableArray{T}"/> value.
+ /// </summary>
+ /// <typeparam name="T">The type of elements in the input <see cref="ImmutableArray{T}"/> value.</typeparam>
+ /// <param name="array">The input <see cref="ImmutableArray{T}"/> value to get the underlying <typeparamref name="T"/> array from.</param>
+ /// <returns>The underlying <typeparamref name="T"/> array for <paramref name="array"/>, if present.</returns>
+ /// <remarks>
+ /// <para>
+ /// When using this method, callers should make sure to not pass the resulting underlying array to methods that
+ /// might mutate it. Doing so might cause undefined behavior in code paths using <paramref name="array"/> which
+ /// don't expect the contents of the <see cref="ImmutableArray{T}"/> value to change.
+ /// </para>
+ /// <para>
+ /// If <paramref name="array"/> is uninitialized (ie. its <see cref="ImmutableArray{T}.IsDefault"/> property is
+ /// <see langword="true"/>), the resulting <typeparamref name="T"/> array will be <see langword="null"/>.
+ /// </para>
+ /// </remarks>
+ public static T[]? AsArray<T>(ImmutableArray<T> array)
+ {
+ return array.array;
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Xunit;
+
+namespace System.Collections.Immutable.Tests
+{
+ public class ImmutableCollectionsMarshalTest
+ {
+ [Fact]
+ public void AsImmutableArrayFromNullArray()
+ {
+ Assert.True(ImmutableCollectionsMarshal.AsImmutableArray<int>(null).IsDefault);
+ Assert.True(ImmutableCollectionsMarshal.AsImmutableArray<int?>(null).IsDefault);
+ Assert.True(ImmutableCollectionsMarshal.AsImmutableArray<Guid>(null).IsDefault);
+ Assert.True(ImmutableCollectionsMarshal.AsImmutableArray<Guid?>(null).IsDefault);
+ Assert.True(ImmutableCollectionsMarshal.AsImmutableArray<string>(null).IsDefault);
+ Assert.True(ImmutableCollectionsMarshal.AsImmutableArray<CustomClass>(null).IsDefault);
+ Assert.True(ImmutableCollectionsMarshal.AsImmutableArray<ManagedCustomStruct>(null).IsDefault);
+ Assert.True(ImmutableCollectionsMarshal.AsImmutableArray<ManagedCustomStruct?>(null).IsDefault);
+ Assert.True(ImmutableCollectionsMarshal.AsImmutableArray<UnmanagedCustomStruct>(null).IsDefault);
+ Assert.True(ImmutableCollectionsMarshal.AsImmutableArray<UnmanagedCustomStruct?>(null).IsDefault);
+ }
+
+ [Fact]
+ public void AsImmutableArrayFromEmptyArray()
+ {
+ Assert.True(ImmutableCollectionsMarshal.AsImmutableArray(Array.Empty<int>()).IsEmpty);
+ Assert.True(ImmutableCollectionsMarshal.AsImmutableArray(Array.Empty<int?>()).IsEmpty);
+ Assert.True(ImmutableCollectionsMarshal.AsImmutableArray(Array.Empty<Guid>()).IsEmpty);
+ Assert.True(ImmutableCollectionsMarshal.AsImmutableArray(Array.Empty<Guid?>()).IsEmpty);
+ Assert.True(ImmutableCollectionsMarshal.AsImmutableArray(Array.Empty<string>()).IsEmpty);
+ Assert.True(ImmutableCollectionsMarshal.AsImmutableArray(Array.Empty<CustomClass>()).IsEmpty);
+ Assert.True(ImmutableCollectionsMarshal.AsImmutableArray(Array.Empty<ManagedCustomStruct>()).IsEmpty);
+ Assert.True(ImmutableCollectionsMarshal.AsImmutableArray(Array.Empty<ManagedCustomStruct?>()).IsEmpty);
+ Assert.True(ImmutableCollectionsMarshal.AsImmutableArray(Array.Empty<UnmanagedCustomStruct>()).IsEmpty);
+ Assert.True(ImmutableCollectionsMarshal.AsImmutableArray(Array.Empty<UnmanagedCustomStruct?>()).IsEmpty);
+ }
+
+ [Fact]
+ public void AsImmutableArrayFromExistingArray()
+ {
+ static void Test<T>()
+ {
+ T[] array = new T[17];
+ ImmutableArray<T> immutableArray = ImmutableCollectionsMarshal.AsImmutableArray(array);
+
+ Assert.False(immutableArray.IsDefault);
+ Assert.Equal(17, immutableArray.Length);
+
+ ref T expectedRef = ref array[0];
+ ref T actualRef = ref Unsafe.AsRef(in immutableArray.ItemRef(0));
+
+ Assert.True(Unsafe.AreSame(ref expectedRef, ref actualRef));
+ }
+
+ Test<int>();
+ Test<int?>();
+ Test<Guid>();
+ Test<Guid?>();
+ Test<string>();
+ Test<CustomClass>();
+ Test<ManagedCustomStruct>();
+ Test<ManagedCustomStruct?>();
+ Test<UnmanagedCustomStruct>();
+ Test<UnmanagedCustomStruct?>();
+ }
+
+ [Fact]
+ public void AsArrayFromDefaultImmutableArray()
+ {
+ Assert.Null(ImmutableCollectionsMarshal.AsArray<int>(default));
+ Assert.Null(ImmutableCollectionsMarshal.AsArray<int?>(default));
+ Assert.Null(ImmutableCollectionsMarshal.AsArray<Guid>(default));
+ Assert.Null(ImmutableCollectionsMarshal.AsArray<Guid?>(default));
+ Assert.Null(ImmutableCollectionsMarshal.AsArray<string>(default));
+ Assert.Null(ImmutableCollectionsMarshal.AsArray<CustomClass>(default));
+ Assert.Null(ImmutableCollectionsMarshal.AsArray<ManagedCustomStruct>(default));
+ Assert.Null(ImmutableCollectionsMarshal.AsArray<ManagedCustomStruct?>(default));
+ Assert.Null(ImmutableCollectionsMarshal.AsArray<UnmanagedCustomStruct>(default));
+ Assert.Null(ImmutableCollectionsMarshal.AsArray<UnmanagedCustomStruct?>(default));
+ }
+
+ [Fact]
+ public void AsArrayFromEmptyImmutableArray()
+ {
+ static void Test<T>()
+ {
+ T[]? array = ImmutableCollectionsMarshal.AsArray(ImmutableArray<T>.Empty);
+
+ Assert.NotNull(array);
+ Assert.Empty(array);
+ }
+
+ Test<int>();
+ Test<int?>();
+ Test<Guid>();
+ Test<Guid?>();
+ Test<string>();
+ Test<CustomClass>();
+ Test<ManagedCustomStruct>();
+ Test<ManagedCustomStruct?>();
+ Test<UnmanagedCustomStruct>();
+ Test<UnmanagedCustomStruct?>();
+ }
+
+ [Fact]
+ public void AsArrayFromConstructedImmutableArray()
+ {
+ static void Test<T>()
+ {
+ ImmutableArray<T> immutableArray = ImmutableArray.Create(new T[17]);
+ T[]? array = ImmutableCollectionsMarshal.AsArray(immutableArray);
+
+ Assert.NotNull(array);
+ Assert.Equal(17, array.Length);
+
+ ref T expectedRef = ref Unsafe.AsRef(in immutableArray.ItemRef(0));
+ ref T actualRef = ref array[0];
+
+ Assert.True(Unsafe.AreSame(ref expectedRef, ref actualRef));
+ }
+
+ Test<int>();
+ Test<int?>();
+ Test<Guid>();
+ Test<Guid?>();
+ Test<string>();
+ Test<CustomClass>();
+ Test<ManagedCustomStruct>();
+ Test<ManagedCustomStruct?>();
+ Test<UnmanagedCustomStruct>();
+ Test<UnmanagedCustomStruct?>();
+ }
+
+ public class CustomClass
+ {
+ public object Foo;
+ public Guid Bar;
+ }
+
+ public struct ManagedCustomStruct
+ {
+ public object Foo;
+ public Guid Bar;
+ }
+
+ public struct UnmanagedCustomStruct
+ {
+ public Guid Foo;
+ public int Bar;
+ }
+ }
+}
<Compile Include="Frozen\FrozenFromKnownValuesTests.cs" />
<Compile Include="Frozen\KeyAnalyzerTests.cs" />
<Compile Include="ImmutableArrayExtensionsTest.cs" />
+ <Compile Include="ImmutableCollectionsMarshal.cs" />
<Compile Include="ImmutableArrayTest.cs" />
<Compile Include="ImmutableArrayTest.netcoreapp.cs" Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp'" />
<Compile Include="ImmutableArrayTestBase.cs" />
<Compile Include="System\Reflection\Internal\Utilities\StreamExtensions.netcoreapp.cs" Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp'" />
<Compile Include="System\Reflection\Internal\Utilities\StreamExtensions.netstandard2.0.cs" Condition="'$(TargetFrameworkIdentifier)' != '.NETCoreApp'" />
<Compile Include="System\Reflection\Internal\Utilities\Hash.cs" />
- <Compile Include="System\Reflection\Internal\Utilities\ImmutableByteArrayInterop.cs" />
<Compile Include="System\Reflection\Internal\Utilities\ImmutableMemoryStream.cs" />
<Compile Include="System\Reflection\Internal\Utilities\MemoryBlock.cs" />
<Compile Include="System\Reflection\Internal\Utilities\PooledStringBuilder.cs" />
using System.Collections.Immutable;
using System.Diagnostics;
using System.IO;
+using System.Runtime.InteropServices;
using System.Threading;
namespace System.Reflection.Internal
{
if (_pinned == null)
{
- var newPinned = new PinnedObject(ImmutableByteArrayInterop.DangerousGetUnderlyingArray(_array)!);
+ var newPinned = new PinnedObject(ImmutableCollectionsMarshal.AsArray(_array)!);
if (Interlocked.CompareExchange(ref _pinned, newPinned, null) != null)
{
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Collections.Immutable;
-using System.Diagnostics.CodeAnalysis;
-using System.Runtime.CompilerServices;
-
-namespace System.Reflection.Internal
-{
- /// <summary>
- /// Provides tools for using <see cref="ImmutableArray{Byte}"/> in interop scenarios.
- /// </summary>
- /// <remarks>
- /// *** WARNING ***
- ///
- /// If you decide to copy this code elsewhere, please retain the documentation here
- /// and the Dangerous prefixes in the API names. This will help track down and audit
- /// other places where this technique (with dangerous consequences when misused) may
- /// be applied.
- ///
- /// A generic version of this API was once public in a pre-release of immutable
- /// collections, but it was deemed to be too subject to abuse when available publicly.
- ///
- /// This implementation is scoped to byte arrays as that is all that the metadata reader needs.
- ///
- /// Also, since we don't have access to immutable collection internals, we use
- /// <see cref="Unsafe.As{TFrom, TTo}(ref TFrom)"/>.
- ///
- /// The fact that <see cref="ImmutableArray{Byte}"/> is backed by a single byte array
- /// field is something inherent to the design of ImmutableArray in order to get its performance
- /// characteristics and therefore something we (Microsoft) are comfortable defining as a contract that
- /// can be depended upon as below.
- /// </remarks>
- internal static unsafe class ImmutableByteArrayInterop
- {
- /// <summary>
- /// Creates a new instance of <see cref="ImmutableArray{Byte}"/> using a given mutable array as the backing
- /// field, without creating a defensive copy. It is the responsibility of the caller to ensure no other mutable
- /// references exist to the array. Do not mutate the array after calling this method.
- /// </summary>
- /// <param name="array">The mutable array to use as the backing field. The incoming reference is set to null
- /// since it should not be retained by the caller.</param>
- /// <remarks>
- /// Users of this method should take extra care to ensure that the mutable array given as a parameter
- /// is never modified. The returned <see cref="ImmutableArray{T}"/> will use the given array as its backing
- /// field without creating a defensive copy, so changes made to the given mutable array will be observable
- /// on the returned <see cref="ImmutableArray{T}"/>. Instance and static methods of <see cref="ImmutableArray{T}"/>
- /// and <see cref="ImmutableArray"/> may malfunction if they operate on an <see cref="ImmutableArray{T}"/> instance
- /// whose underlying backing field is modified.
- /// </remarks>
- /// <returns>An immutable array.</returns>
- internal static ImmutableArray<byte> DangerousCreateFromUnderlyingArray(ref byte[]? array)
- {
- byte[] givenArray = array!;
- array = null;
-
- return Unsafe.As<byte[], ImmutableArray<byte>>(ref givenArray);
- }
-
- /// <summary>
- /// Access the backing mutable array instance for the given <see cref="ImmutableArray{T}"/>, without
- /// creating a defensive copy. It is the responsibility of the caller to ensure the array is not modified
- /// through the returned mutable reference. Do not mutate the returned array.
- /// </summary>
- /// <param name="array">The <see cref="ImmutableArray{T}"/> from which to retrieve the backing field.</param>
- /// <remarks>
- /// Users of this method should take extra care to ensure that the returned mutable array is never modified.
- /// The returned mutable array continues to be used as the backing field of the given <see cref="ImmutableArray{T}"/>
- /// without creating a defensive copy, so changes made to the returned mutable array will be observable
- /// on the given <see cref="ImmutableArray{T}"/>. Instance and static methods of <see cref="ImmutableArray{T}"/>
- /// and <see cref="ImmutableArray"/> may malfunction if they operate on an <see cref="ImmutableArray{T}"/> instance
- /// whose underlying backing field is modified.
- /// </remarks>
- /// <returns>The underlying array, or null if <see cref="ImmutableArray{T}.IsDefault"/> is true.</returns>
- internal static byte[]? DangerousGetUnderlyingArray(ImmutableArray<byte> array)
- {
- return Unsafe.As<ImmutableArray<byte>, byte[]>(ref array);
- }
- }
-}
public ImmutableArray<byte> ToImmutableArray(int start, int byteCount)
{
byte[]? array = ToArray(start, byteCount);
- return ImmutableByteArrayInterop.DangerousCreateFromUnderlyingArray(ref array);
+ return ImmutableCollectionsMarshal.AsImmutableArray(array);
}
internal bool TryGetSpan(out ReadOnlySpan<byte> buffer)
public ImmutableArray<byte> GetILContent()
{
byte[]? bytes = GetILBytes();
- return ImmutableByteArrayInterop.DangerousCreateFromUnderlyingArray(ref bytes);
+ return ImmutableCollectionsMarshal.AsImmutableArray(bytes);
}
public BlobReader GetILReader()
using System.Diagnostics;
using System.Reflection.Internal;
using System.Reflection.Metadata.Ecma335;
+using System.Runtime.InteropServices;
using System.Text;
namespace System.Reflection.Metadata
externalTableRowCounts = ReadMetadataTableRowCounts(ref reader, externalTableMask);
debugMetadataHeader = new DebugMetadataHeader(
- ImmutableByteArrayInterop.DangerousCreateFromUnderlyingArray(ref pdbId),
+ ImmutableCollectionsMarshal.AsImmutableArray(pdbId),
MethodDefinitionHandle.FromRowId(entryPointRowId),
idStartOffset: pdbStreamOffset);
}
{
// TODO: We can skip a copy for virtual blobs.
byte[]? bytes = GetBlobBytes(handle);
- return ImmutableByteArrayInterop.DangerousCreateFromUnderlyingArray(ref bytes);
+ return ImmutableCollectionsMarshal.AsImmutableArray(bytes);
}
public BlobReader GetBlobReader(BlobHandle handle)
using System.Reflection.Internal;
using System.Reflection.Metadata;
using System.Runtime.ExceptionServices;
+using System.Runtime.InteropServices;
using System.Threading;
using ImmutableArrayExtensions = System.Linq.ImmutableArrayExtensions;
return new PdbChecksumDebugDirectoryData(
algorithmName,
- ImmutableByteArrayInterop.DangerousCreateFromUnderlyingArray(ref checksum));
+ ImmutableCollectionsMarshal.AsImmutableArray(checksum));
}
/// <summary>
<Compile Include="Utilities\StringUtilsTests.cs" />
<Compile Include="Utilities\BlobReaderTests.cs" />
<Compile Include="Utilities\CompressedIntegerTests.cs" />
- <Compile Include="Utilities\ImmutableByteArrayInteropTest.cs" />
<Compile Include="Utilities\MemoryBlockTests.cs" />
<Compile Include="Utilities\OrderByTests.cs" />
</ItemGroup>
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Immutable;
-using System.Reflection.Internal;
using System.Runtime.InteropServices;
namespace System.Reflection.Metadata.Tests
private readonly byte[] _blob;
public PinnedBlob(ImmutableArray<byte> blob)
- : this(ImmutableByteArrayInterop.DangerousGetUnderlyingArray(blob))
+ : this(ImmutableCollectionsMarshal.AsArray(blob))
{
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Collections.Immutable;
-using System.Reflection.Internal;
-using Xunit;
-
-namespace System.Reflection.Metadata.Tests
-{
- public class ImmutableByteArrayInteropTest
- {
- [Fact]
- public void DangerousCreateFromUnderlyingArray()
- {
- byte[] array = new byte[3] { 1, 2, 3 };
- byte[] arrayCopy = array;
- ImmutableArray<byte> immutable = ImmutableByteArrayInterop.DangerousCreateFromUnderlyingArray(ref array);
-
- // DangerousCreateFromUnderlyingArray clears the given parameter as a signal that
- // the mutable array should no longer be modified through mutable references.
- Assert.Null(array);
-
- Assert.Equal(3, immutable.Length);
- Assert.Equal(1, immutable[0]);
- Assert.Equal(2, immutable[1]);
- Assert.Equal(3, immutable[2]);
-
- arrayCopy[0] = 9;
-
- Assert.Equal(9, immutable[0]);
- }
-
- [Fact]
- public void DangerousCreateFromUnderlyingArrayNegativeTests()
- {
- byte[] array = null;
- ImmutableArray<byte> immutable = ImmutableByteArrayInterop.DangerousCreateFromUnderlyingArray(ref array);
-
- Assert.True(immutable.IsDefault);
- }
-
- [Fact]
- public void DangerousGetUnderlyingArray()
- {
- ImmutableArray<byte> immutable = ImmutableArray.Create<byte>(1, 2, 3);
- byte[] array = ImmutableByteArrayInterop.DangerousGetUnderlyingArray(immutable);
-
- Assert.Equal(3, array.Length);
- Assert.Equal(1, array[0]);
- Assert.Equal(2, array[1]);
- Assert.Equal(3, array[2]);
-
- array[0] = 9;
-
- Assert.Equal(9, immutable[0]);
- }
-
- [Fact]
- public void DangerousGetUnderlyingArrayNegativeTests()
- {
- ImmutableArray<byte> immutable = default(ImmutableArray<byte>);
-
- Assert.Null(ImmutableByteArrayInterop.DangerousGetUnderlyingArray(immutable));
- }
- }
-}