It's guaranteed from the perspective of Fjuk but not of Main.
In Fjuk the exception is thrown after the parameter is set. While there can be re-orderings done by compiler, jitter, and CPU, there will not be re-orderings such that the order observed by a single thread changes. Since a single thread could "notice" if the parameter wasn't set before the exception thrown, the parameter is guaranteed to be set.
In Main though, we have no knowledge of the details of Fjuk's implementation, so when the compiler analyses Main, it can't depend on that. Hence in the variation where we don't assign a value to s before the call:
static void Main()
{
string s;
try
{
Fjuk(out s);
Console.WriteLine(s ?? "");//fine
}
catch (Exception)
{
Console.WriteLine(s ?? "");//compiler error
}
Console.WriteLine(s ?? "");//compiler error
}
The first attempt to use s immediately after the call to Fjuk is fine, because one can only get there if Fjuk succeeded, and if Fjuk succeeded then s must be assigned. In the second and third case though, it's possible to arrive at those lines without Fjuk succeeding, and since one cannot tell by analysis of Main whether an exception could be thrown before s is set, the uses of s must be prohibited.