Используйте Span<T> в качестве переменной уровня класса C#

Я пишу высокопроизводительный парсер для потока с разделителями-запятыми (сети). Моя цель — разобрать и преобразовать напрямую из двоичных файлов в примитивы dotnet. Основываясь на моем тестировании до сих пор, производительность Span невероятна, но с этим типом сложно работать из-за ограничений, присущих структурам ref. Я столкнулся с препятствием, пытаясь найти эффективный способ хранения констант Span (запятая, новая строка и т. д.), используемых в моем приложении. Единственное решение, которое существует, чтобы хранить их как byte и преобразовывать их в тела классов методов... или жестко кодировать Span<byte> delimiter = Encoding.UTF8.GetBytes("\r\n") в тело каждого метода.

Я хотел бы добиться следующего, но выдает ошибку: «CS8345 Поле или автоматически реализуемое свойство не может иметь тип «Span», если только оно не является членом экземпляра структуры ref.

public class Parser
{
    Span<byte> NewLine = new byte[]{ (byte)'\n' };
}

Должен быть лучший способ! Пожалуйста помоги!

Стоит ли изучать 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
0
64
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете создать ReadOnlySpan<byte> с литералом UTF-8 в .NET 7:

class Consts
{
    public static ReadOnlySpan<byte> Delim => "\n"u8;
}

Или используйте Memory/ReadOnlyMemory:

public class Consts 
{
    public static ReadOnlyMemory<int> Type { get; } = new []{1};
}

И использование:

ReadOnlySpan<int> span = Consts.Type.Span;

Или украсьте вышеупомянутый подход свойством метода/выражения:

class Consts
{
    private static readonly byte[] _delim = { (byte)'\n' };
    public static ReadOnlySpan<byte> Delim => _delim;
}

Демо

См. выше, как это сделать напрямую с помощью Span<T>.

Adam Cohen 18.02.2023 10:02

@AdamCohen, посмотри мой комментарий.

Guru Stron 18.02.2023 10:08
Ответ принят как подходящий

Вы сталкиваетесь с проблемами, потому что ref structs, как и Span<T>, являются специальными типами данных с ограничениями, которые гарантируют, что они не могут выйти из стека. Classes — это ссылочные типы, которые живут в куче. Таким образом, если бы Span был членом класса, это нарушило бы правило «только стек». Тем не менее, статические свойства, которые реализованы (не автоматически реализуются, например, { get; set;}), разрешены и кажутся решением, которое вы ищете. См. следующий пример...

public class Parser
{
    static Span<byte> NewLine => { (byte)'\n' };
    static ReadOnlySpan<byte> Comma => { (byte)',' };

    private static Span<byte> TraditionSyntax
    {
        get
        {
            return new[] {(byte)'\n' };
        } 
    }
}

Обратите внимание, что синтаксис "string"u8.Array() — это литерал, который преобразует строку непосредственно в UTF8, как если бы вы вызывали кодировщик так, как указано в вашем примере. Тем не менее, обязательно проверьте литерал, чтобы убедиться, что он дает то, что вы ожидаете. Это не всегда соответствует Encoding.UTF8.

Не отвлекайтесь на тело метода (геттер свойств). Существует оптимизация компилятора, которая позволяет избежать выделения памяти при использовании (byte).

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

Guru Stron 18.02.2023 10:07

Неа. Для этого есть оптимизация компилятора. См. выше.

acoder 18.02.2023 10:24

Я исправил использование (byte) '\n' в одном из примеров, чтобы избежать путаницы. Надеюсь это поможет.

acoder 18.02.2023 10:26

@acoder Я не вижу никаких @sharplab

Guru Stron 18.02.2023 10:27

@acoder и память распределяются в соответствии с GC.GetTotalAllocatedBytes - Demo

Guru Stron 18.02.2023 10:37

«Обратите внимание, что синтаксис «string» u8.Array () является литералом, который преобразует строку непосредственно в UTF8» - не могли бы вы поделиться доказательством утверждения.

Guru Stron 18.02.2023 10:38
public static ReadOnlySpan<byte> NewLine => "\n"u8; буквально.
Guru Stron 18.02.2023 10:41

@GuruStron - в теле моего метода TraditionalSyntax используется версия, оптимизированная для компилятора (поскольку вы обновили свой ответ до реплицированного). Два других примера просто иллюстрируют, как использовать ярлык Encoder.UTF8.GetBytes(). И все вышеперечисленное должно быть оптимизировано в .Net7 Roslyn, хотя я не уверен на 100%, что он был выпущен.

Adam Cohen 18.02.2023 10:41

@AdamCohen «И все вышеперечисленное должно быть оптимизировано с помощью .Net7 Roslyn» - на основе декомпиляции и моих тестов - это не так. Еще раз - не могли бы вы поделиться документами?

Guru Stron 18.02.2023 10:47

Похоже, это Net8.0. Предполагалось, что они устранят необходимость в .ToArray()...learn.microsoft.com/en-us/dotnet/csharp/languag‌​e-reference/… , и на github есть обсуждения и множество PR. Нет времени на поиски, но я уверен, что вы можете найти через Google. Над ним работают Туб и еще несколько лучших парней. Надеюсь это поможет

Adam Cohen 18.02.2023 11:23

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