Разбираясь с совместимостью собственного кода, я решил, что пришло время изучить и опробовать новые возможности Span языка C#.
Хотя во многих испытаниях все шло отлично, пока я не подошел к заключительному этапу моей очень длинной функции, для которой я вставляю ниже лишь минимальный воспроизводимый образец:
[DllImport(dll, SetLastError = true)]
internal static extern void GetNativeData(out byte lpBuffer, int size, out bytesRead);
ReadOnlySpan ReadArray(ReadOnlySpan buf, int Length) where T : unmanaged
{
var size = Length * Unsafe.SizeOf();
if (buf.Length < size)
buf = new byte[size];
GetNativeData(out MemoryMarshal.GetReference(buf), size, out int read));
Dh.CreateError(ReadMemoryErr);
return MemoryMarshal.Cast(buf.Slice(0, size));
}
static IEnumerable GetResult()
{
// Here I allocate a buffer
Span buf = new byte[1000];
// After a long serie of calls to unmanaged DLL functions I end up with something like this:
ReadOnlySpan uintRes = data.ReadArray(buf, 10);
ReadOnlySpan shortRes = data.ReadArray(buf, 10);
for (int i = 0; i < uintRes.Length; i++)
{
// Any access to spans inside this loop result in Error CS4013
string r = GetFunRes(uintRes);
IntPtr r2 = GetFunRes2(shortRes);
yield return new MyClass() { Prop1 = r, Prop2 = r2 };
}
}
Я получаю следующую ошибку:
Ошибка CS4013: экземпляр типа «Span» нельзя использовать внутри
вложенной функции, выражения запроса, блока итератора или асинхронного метода
Я прочитал, что для этой проблемы существуют обходные пути. В статьях показано только использование асинхронных методов, но также указано, что это применимо и к итераторам. К сожалению, мне не удалось выполнить эту работу. Мне нужно только прочитать определенные элементы диапазона, а затем получить результат, который не содержит никаких элементов или ссылок на диапазон. Просто, что бы я ни пытался сделать, как только я пытаюсь получить к чему-то доступ, компилятор терпит неудачу.
Я читал о Memory, и, возможно, этот вариант может работать, но у меня есть некоторые опасения, поскольку я читал, что производительность резко снижается. Люди также рекомендуют Span в первую очередь. Надеюсь, я смогу найти решение, потому что в противном случае мне придется перезапускать свой проект с нуля и все переписывать, потому что теперь он жестко привязан к Span.
@00110001:
var uintRes = data.ReadArray(buf, 10).ToArray();
Я знаю, что это сработает, но полагаю, что это сделает бесполезным использование Span вместе с новыми неуправляемыми функциями универсальных функций, которыми я пытаюсь воспользоваться (ReadArray). Если я не ошибаюсь, вызов ToArray() аналогичен старому стилю маршалинга, когда для каждого вызова создается новая копия:
internal static extern void GetNativeData(out uint[] lpBuffer, int size, out bytesRead);
@Ian Kemp
Вот как я попробовал обходной путь, упомянутый в статье:
int len = uintRes.Length;
for (int i = 0; i < len; i++)
{
var res = ParseData(i);
if (res == ExpectedResult())
yield return res;
}
MyClass ParseData(int index)
{
// CS8175: Cannot use ref local 'uintRes, shortRes' inside an anonymous method, lambda expression, or query expression
string r = GetFunRes(uintRes[index]);
IntPtr r2 = GetFunRes2(shortRes[index]);
return new MyClass() { Prop1 = r, Prop2 = r2 };
}
Подробнее здесь: https://stackoverflow.com/questions/663 ... urns-an-ie
Требуется обходной путь для доступа к ReadOnlySpan внутри функции, которая возвращает IEnumerable ⇐ C#
Место общения программистов C#
1766075793
Anonymous
Разбираясь с совместимостью собственного кода, я решил, что пришло время изучить и опробовать новые возможности Span языка C#.
Хотя во многих испытаниях все шло отлично, пока я не подошел к заключительному этапу моей очень длинной функции, для которой я вставляю ниже лишь минимальный воспроизводимый образец:
[DllImport(dll, SetLastError = true)]
internal static extern void GetNativeData(out byte lpBuffer, int size, out bytesRead);
ReadOnlySpan ReadArray(ReadOnlySpan buf, int Length) where T : unmanaged
{
var size = Length * Unsafe.SizeOf();
if (buf.Length < size)
buf = new byte[size];
GetNativeData(out MemoryMarshal.GetReference(buf), size, out int read));
Dh.CreateError(ReadMemoryErr);
return MemoryMarshal.Cast(buf.Slice(0, size));
}
static IEnumerable GetResult()
{
// Here I allocate a buffer
Span buf = new byte[1000];
// After a long serie of calls to unmanaged DLL functions I end up with something like this:
ReadOnlySpan uintRes = data.ReadArray(buf, 10);
ReadOnlySpan shortRes = data.ReadArray(buf, 10);
for (int i = 0; i < uintRes.Length; i++)
{
// Any access to spans inside this loop result in Error CS4013
string r = GetFunRes(uintRes[i]);
IntPtr r2 = GetFunRes2(shortRes[i]);
yield return new MyClass() { Prop1 = r, Prop2 = r2 };
}
}
Я получаю следующую ошибку:
Ошибка CS4013: экземпляр типа «Span» нельзя использовать внутри
вложенной функции, выражения запроса, блока итератора или асинхронного метода
Я прочитал, что для этой проблемы существуют обходные пути. В статьях показано только использование асинхронных методов, но также указано, что это применимо и к итераторам. К сожалению, мне не удалось выполнить эту работу. Мне нужно только прочитать определенные элементы диапазона, а затем получить результат, который не содержит никаких элементов или ссылок на диапазон. Просто, что бы я ни пытался сделать, как только я пытаюсь получить к чему-то доступ, компилятор терпит неудачу.
Я читал о Memory, и, возможно, этот вариант может работать, но у меня есть некоторые опасения, поскольку я читал, что производительность резко снижается. Люди также рекомендуют Span в первую очередь. Надеюсь, я смогу найти решение, потому что в противном случае мне придется перезапускать свой проект с нуля и все переписывать, потому что теперь он жестко привязан к Span.
@00110001:
var uintRes = data.ReadArray(buf, 10).ToArray();
Я знаю, что это сработает, но полагаю, что это сделает бесполезным использование Span вместе с новыми неуправляемыми функциями универсальных функций, которыми я пытаюсь воспользоваться (ReadArray). Если я не ошибаюсь, вызов ToArray() аналогичен старому стилю маршалинга, когда для каждого вызова создается новая копия:
internal static extern void GetNativeData(out uint[] lpBuffer, int size, out bytesRead);
@Ian Kemp
Вот как я попробовал обходной путь, упомянутый в статье:
int len = uintRes.Length;
for (int i = 0; i < len; i++)
{
var res = ParseData(i);
if (res == ExpectedResult())
yield return res;
}
MyClass ParseData(int index)
{
// CS8175: Cannot use ref local 'uintRes, shortRes' inside an anonymous method, lambda expression, or query expression
string r = GetFunRes(uintRes[index]);
IntPtr r2 = GetFunRes2(shortRes[index]);
return new MyClass() { Prop1 = r, Prop2 = r2 };
}
Подробнее здесь: [url]https://stackoverflow.com/questions/66379248/need-a-workaround-to-access-readonlyspant-inside-a-function-that-returns-an-ie[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия