Jon Skeet said:
See below.
No, it has to point to an actual reference.
No its not, passing a pointer to a 'null' reference is valid, how would you
explain following is valid, or do you call null an actual reference?.
{
string s;
// or this...
// string s = null;
F(out s);
Console.WriteLine(s);
}
static void F(out string s)
{
s = "test";
}
But that's the point - it's only compiler enforced in C#, and you might
be calling into non-C# code. Even using C#, if you use RealProxy to
implement an interface, you can get that initial value as an object
reference. Imagine if it were a reference to some sensitive piece of
memory elsewhere - very bad news from a security point of view.
But who is talking about a pointer to memory elsewhere, we are talking about
locals here and locals are stack allocated, the variable declaration
reserves the location on the stack to hold the variable (whatever its type)
while the out keyword tells the compiler to take the address of the value as
argument, it MUST point to a valid memory location (this is the JIT's task),
but the 'value' it points to doesn't matter, is not verified and so it can
be bit combination.
That means that in this snip:
string s;
string ss = "Just a string";
// this..
string s = null;
// and these
// string s = "Whatever";
// string s = ss;
F(out s);
...
static void F(out string s)
{
s = ...
}
are all valid, all that's required is that the callee assigns the 'value'
pointed to by the argument (a pointer) before leaving the method scope
(again this is compiler enforced).
So, this is not valid...
static void F(out string s)
{ // do whatever, but don't assign to s... }
It may be up to the callee to know the semantics, but unless the CLI
spec (which I haven't checked) says that those semantics are actually
enforced, you could still have managed code with a nasty security
problem if the "uninitialised" value could be examined.
Hmmm, I didn't say the CLI imposes something here, I was talking about
PInvoke and as the callee is unmanaged code we aren't going to discuss
security and other things that might go wrong, if you call into unmanaged
code, all gates are open. What I meant was when passing an argument as
'out', it's up to the interop layer to correctly marshal the pointer or the
data it points to, depending on the argument type and it's attributes. If
there is something wrong with one of these, bad things can happen and the
CLI has nothing to with this.
Sorry, I'm completely lost here I'm starting to think we are talking about
different things here, the OP and I are saying that locals are initialized
to zero, the while the C# specs. explicitely state that "locals are NOT
initialized and they don't contain default values", note that the specs
don't say "you should not assume that locals are compiler initialized'.
I don't have a problem with this explicit initialization in the current
implementation[1], but the OP's point is the redundant initialization
imposed by the C# compiler (also not an issue for me) , while it's not
required by VB.NET nor by C++/CLI.
// this is redundant in the current implementation, but it's C# compiler
enforced, which is not true for the other compilers.
int aLocal = 0;
[1] all MSFT compilers emit .locals init and as such sets the locals to 0
(not explicitly required as per C# specs).
Willy.