| File: Collections\ArrayElement.cs | Web Access |
| Project: src\roslyn\src\Compilers\Core\Portable\Microsoft.CodeAnalysis.csproj (Microsoft.CodeAnalysis) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.Diagnostics; using System.Diagnostics.CodeAnalysis; namespace Microsoft.CodeAnalysis { [DebuggerDisplay("{Value,nq}")] internal struct ArrayElement<T> { internal T Value; public static implicit operator T(ArrayElement<T> element) { return element.Value; } //NOTE: there is no opposite conversion operator T -> ArrayElement<T> // // that is because it is preferred to update array elements in-place // "elements[i].Value = v" results in much better code than "elements[i] = (ArrayElement<T>)v" // // The reason is that x86 ABI requires that structs must be returned in // a return buffer even if they can fit in a register like this one. // Also since struct contains a reference, the write to the buffer is done with a checked GC barrier // as JIT does not know if the write goes to a stack or a heap location. // Assigning to Value directly easily avoids all this redundancy. [return: NotNullIfNotNull(parameterName: nameof(items))] public static ArrayElement<T>[]? MakeElementArray(T[]? items) { if (items == null) { return null; } var array = new ArrayElement<T>[items.Length]; for (int i = 0; i < items.Length; i++) { array[i].Value = items[i]; } return array; } [return: NotNullIfNotNull(parameterName: nameof(items))] public static T[]? MakeArray(ArrayElement<T>[]? items) { if (items == null) { return null; } var array = new T[items.Length]; for (int i = 0; i < items.Length; i++) { array[i] = items[i].Value; } return array; } } }