Длина встроенного массива

Новой функцией C# 12 являются встроенные массивы, например

[System.Runtime.CompilerServices.InlineArray(10)]
public struct Buffer
{
    private object element;
}

как описано здесь.

Если я определяю экземпляр такого массива, например

Buffer a = new();

Я ожидал, что что-то вроде a.Size или a.Length будет определено как свойство или метод, но это не так.

Я нашел такой способ получить длину буфера: ((ReadOnlySpan<double>)a).Length. Есть ли более элегантный способ?

можешь попробовать a[..].Length

Iłya Bursov 05.08.2024 15:42
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
1
72
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий
[System.Runtime.CompilerServices.InlineArray(Buffer.Length)]
public struct Buffer
{
    private object element;

    public const int Length = 10;  // Define the length as a constant
}

Buffer a = new();
var length = Buffer.Length;

Или

[System.Runtime.CompilerServices.InlineArray(Buffer.length)]
public struct Buffer
{
    private object element;

    private const int length = 10;  // Define the length as a constant
    public int Length => length;
}

Buffer a = new();
var length = a.Length;

В этом примере свойство Длина определяется непосредственно в структуре, что обеспечивает более интуитивный способ доступа к длине буфера. Это свойство просто возвращает постоянный размер встроенного массива. Однако имейте в виду, что этот подход требует ручной синхронизации значения свойства Длина с фактическим размером, определенным в атрибуте InlineArray.

Это не так динамично, как получение длины из ReadOnlySpan, который адаптируется к фактическому типу и размеру буфера, но обеспечивает понятный и простой интерфейс для доступа к длине.

Я предлагаю определить константу: public const int Length = 10;, которую вы можете использовать в атрибуте: [System.Runtime.CompilerServices.InlineArray(Buffer.Length)]

Dmitry Bychenko 05.08.2024 15:28

Я хотел бы сделать модификацию Дмитрия ответа Альберто принятой. Может ли кто-нибудь из вас создать эту версию как новый ответ или изменить существующую?

MarkusParker 06.08.2024 08:32

@MarkusParker обновил код из ОП, чтобы он соответствовал запросу.

Guru Stron 07.08.2024 14:57

Из документации Inline Array:

Язык обеспечит типобезопасный и безопасный по ссылкам способ доступа к элементам встроенных типов массивов. Доступ будет основан на интервале.

Где в следующем разделе рассказывается, как получить интервал.

То есть от вас не ожидается прямого доступа к размеру переменной или членам длины. Вместо этого вы получаете Span и используете его для управления массивом. Кроме того, поскольку массивы имеют фиксированный размер, вы уже должны знать .Length на основе аргумента атрибута, указанного при объявлении структуры.

Я ожидал, что что-то вроде a.Size или a.Length будет определено как свойство или метод, но это не так.

К сожалению на данный момент ничего из коробки нет. Как написано в обсуждении в csharplang:

InlineArray предназначен для скрытого резервного хранилища, которое не используется напрямую. Вместо этого вы можете просто свободно обернуть его как диапазон и затем получить все тонкости этой абстракции более высокого уровня.

И

Честно говоря, единственный ответ здесь — просто привести его к Span<T>, а затем получить длину. Он преодолевает некоторые препятствия, но, по крайней мере, среда выполнения кажется вполне способной сложить все и просто вернуть постоянное значение.

В основном то, что вы уже обнаружили:

Buffer a = new();
Console.WriteLine(((Span<object>)a).Length);

Использование оператора диапазона ([..], который выглядит немного более эзотерично, но гораздо короче) приводит к созданию того же IL-кода:

Console.WriteLine(a[..].Length);
// decompiled generated code
Console.WriteLine(<PrivateImplementationDetails>.InlineArrayAsSpan<Buffer, object>(ref buffer, 10).Length);

демо @sharplab.io

Как вариант, вы можете написать генератор исходного кода, который будет генерировать некоторые методы расширения для всех встроенных массивов.

P.S.

Утверждение «но, по крайней мере, среда выполнения кажется вполне способной сложить все и просто вернуть постоянное значение» - утверждение кажется неверным, основываясь на JIT ASM, созданном Sharplab.io.

«по крайней мере, среда выполнения кажется вполне способной складывать все и просто возвращать постоянное значение», похоже, не поддерживается JIT ASM в Sharplab

Charlieface 06.08.2024 14:50

@Charlieface да, у меня тоже возникло такое чувство, глядя на это, но у него не было времени исследовать больше. Обновлю ответ, спасибо.

Guru Stron 06.08.2024 20:32

Другие вопросы по теме