Warum macht ein Stackalloc mit Null-Länge den C# Compiler glücklich, bedingte Stackallocs zuzulassen?C#

Ein Treffpunkt für C#-Programmierer
Anonymous
 Warum macht ein Stackalloc mit Null-Länge den C# Compiler glücklich, bedingte Stackallocs zuzulassen?

Post by Anonymous »

Das folgende "Fix" ist für mich sehr verwirrend; Das Szenario hier ist die entscheidende Entscheidung, ob der Stapel gegen einen gemieteten Puffer in Abhängigkeit von der Größe verwendet werden soll - eine hübsche Nische, aber manchmal unbedingt eine optimierte Optimierung: Mit der "offensichtlichen" Implementierung (Nummer 3, die eindeutige Zuordnung aufschoben, bis wir es tatsächlich zuweisen wollen), beschwert sich der Compiler mit CS8353: < /p> < /p>

< /p> < /p>
< /p> < /p>
< /p>
< /p> < /p>
< /p> < /p>
< /p> < /p>
< /p> < /p>
< /p> < /p>

' kann in diesem Zusammenhang nicht verwendet werden, da es außerhalb der enthaltenden Methode entlarvt werden kann.

Code: Select all

// 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
Das einzige, was ich hier denken kann, ist, dass der Compiler Wirklich markiert, dass der Stackalloc dem Kontext entkommt, in dem der Stackalloc stattfindet, und wedelt mit einer Flagge, um zu sagen "Ich kann nicht beweisen, ob dies später sicher sein wird." Umfang höher, und jetzt ist der Compiler froh, dass er niemals dem "gefährlichen" Umfang entkommt (d. H. Es lässt die Methode nie, da wir am oberen Bereich deklarieren). Ist dieses Verständnis richtig und es ist nur eine Compiler-Einschränkung in Bezug auf das, was bewiesen werden kann? an die fehlgeschlagene Nummer 2 = Standard .

Code: Select all

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);
}
}

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post