Почему стекаллок нулевой длины делает компилятор C# довольным разрешать условные стекаллоки?C#

Место общения программистов C#
Ответить
Anonymous
 Почему стекаллок нулевой длины делает компилятор C# довольным разрешать условные стекаллоки?

Сообщение Anonymous »

Следующее «Исправление» мне очень сбивает с толку; the scenario here is conditionally deciding whether to use the stack vs a leased buffer depending on the size - a pretty niche but sometimes-necessary optimization, however: with the "obvious" implementation (number 3, deferring definite assignment until we actually want to assign it), the compiler complains with CS8353:

A result of a stackalloc expression of type 'Span ' не может быть использован в этом контексте, потому что он может быть выявлен за пределами содержащего метода < /p>
< /blockquote>
Короткая репро (полная репробус// take your pick of:
// Span s = stackalloc[0]; // works
// Span s = default; // fails
// Span s; // fails

if (condition)
{ // CS8353 happens here
s = stackalloc int[size];
}
else
{
s = // some other expression
}
// use s here

Единственное, что я могу думать здесь, это то, что компилятор действительно отмечает, что stackalloc избегает контекста, в котором происходит Stackalloc , и размахивает флагом, чтобы сказать «Я не могу доказать, будет ли это в безопасности позже в методе», но мы с теми, что начнется, «начнется». Выше, и теперь компилятор рад, что он никогда не ускользает от «опасного» применения (то есть он никогда не покидает метод, поскольку мы объявляем в верхней области). Правильно ли это понимание, и это просто ограничение компилятора с точки зрения того, что может быть доказано? Сбой номер 2 = по умолчанию .
Full Repro (также доступен на Sharplab для просмотра IL).using System;
using System.Buffers;

public static class C
{
public static void StackAllocFun(int count)
{
// #1 this is legal, just initializes s as a default span
Span s = stackalloc int[0];

// #2 this is illegal: error CS8353: A result of a stackalloc expression
// of type 'Span' cannot be used in this context because it may
// be exposed outside of the containing method
// Span s = default;

// #3 as is this (also illegal, identical error)
// Span s;

int[] oversized = null;
try
{
if (count < 32)
{ // CS8353 happens at this stackalloc
s = stackalloc int[count];
}
else
{
oversized = ArrayPool.Shared.Rent(count);
s = new Span(oversized, 0, count);
}
Populate(s);
DoSomethingWith(s);
}
finally
{
if (oversized is not null)
{
ArrayPool.Shared.Return(oversized);
}
}
}

private static void Populate(Span s)
=> throw new NotImplementedException(); // whatever
private static void DoSomethingWith(ReadOnlySpan s)
=> throw new NotImplementedException(); // whatever

// note: ShowNoOpX and ShowNoOpY compile identically just:
// ldloca.s 0, initobj Span, ldloc.0
static void ShowNoOpX()
{
Span s = stackalloc int[0];
DoSomethingWith(s);
}
static void ShowNoOpY()
{
Span s = default;
DoSomethingWith(s);
}
}


Подробнее здесь: https://stackoverflow.com/questions/672 ... llow-condi
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»