Используйте 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 на IIS без использования программы установки веб-платформы
Запуск PHP на IIS без использования программы установки веб-платформы
Установщик веб-платформы, предлагаемый компанией Microsoft, перестанет работать 31 декабря 2022 года. Его закрытие привело к тому, что мы не можем...
Оптимизация React Context шаг за шагом в 4 примерах
Оптимизация React Context шаг за шагом в 4 примерах
При использовании компонентов React в сочетании с Context вы можете оптимизировать рендеринг, обернув ваш компонент React в React.memo сразу после...
Библиотека для работы с мороженым
Библиотека для работы с мороженым
Лично я попрощался с операторами print() в python. Без шуток.
Настройка шаблона Metronic с помощью Webpack и Gulp
Настройка шаблона Metronic с помощью Webpack и Gulp
Я пишу эту статью, чтобы поделиться тем, как настроить макет Metronic с помощью Sass, поскольку Metronic предоставляет так много документации, и они...
Уроки CSS 6
Уроки CSS 6
Здравствуйте дорогие читатели, я Ферди Сефа Дюзгюн, сегодня мы продолжим с вами уроки css. Сегодня мы снова продолжим с так называемых классов.
Что такое Css? Для чего он используется?
Что такое Css? Для чего он используется?
CSS, или "Каскадные таблицы стилей", - это язык стилей, используемый в веб-страницах. CSS является одним из основных инструментов веб-разработки...
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

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