C
C#8mo ago
ABp16

Explanation for array initialization peculiarities

I'd like to get an explanation for the following behavior :
Ty[] tys = {};
Console.WriteLine(tys.Length); // This is fine

// Of is a Ty[]
var tup = new Ty.Tuple { Of = {} };
Console.WriteLine(tup.Of.Length); // This causes a null pointer exception
Ty[] tys = {};
Console.WriteLine(tys.Length); // This is fine

// Of is a Ty[]
var tup = new Ty.Tuple { Of = {} };
Console.WriteLine(tup.Of.Length); // This causes a null pointer exception
Why does {} seem to do something different depending on where it is ?
56 Replies
Angius
Angius8mo ago
It shouldn't behave differently
ABp16
ABp16OP8mo ago
And yet, it does haha
Angius
Angius8mo ago
Just to check, though, could you try [] instead of {}?
ABp16
ABp16OP8mo ago
No description
ABp16
ABp16OP8mo ago
in which one ?
Angius
Angius8mo ago
Of = []
ABp16
ABp16OP8mo ago
this is not proper syntax it seems
No description
Angius
Angius8mo ago
What's your .NET version?
ABp16
ABp16OP8mo ago
// Of is a Ty[]
var tup = new Ty.Tuple { Of = new Ty[0] };
Console.WriteLine(tup.Of.Length); // This causes a null pointer exception
// Of is a Ty[]
var tup = new Ty.Tuple { Of = new Ty[0] };
Console.WriteLine(tup.Of.Length); // This causes a null pointer exception
this works fine btw
Angius
Angius8mo ago
This intializes a new array of 0-length explicitly, yes
ABp16
ABp16OP8mo ago
is this what you're looking for ?
No description
Angius
Angius8mo ago
Yeah I guess the [] syntax is 8.0 and up
ABp16
ABp16OP8mo ago
But why does {} initialize a 0 length array in some cases and not in others ?
Angius
Angius8mo ago
¯\_(ツ)_/¯
ABp16
ABp16OP8mo ago
Should I upgrade to that then ? What's the reason for this syntax not working ? This I meant
Angius
Angius8mo ago
Honestly not sure Just tried it on .NET 8 and it doesn't work either
ABp16
ABp16OP8mo ago
Do you think it could be a bug in the compiler ?
Angius
Angius8mo ago
E.g.
No description
Angius
Angius8mo ago
Not sure
ABp16
ABp16OP8mo ago
I'm looking for some sort of specification that says "When classes are initialized this way {} stands for null" or something like that
Angius
Angius8mo ago
Huh, the compiler-generated code is
[CompilerGenerated]
internal class Program
{
private static void <Main>$(string[] args)
{
Ty[] array = new Ty[0];
Ty.Tuple tuple = new Ty.Tuple();
}
}
[CompilerGenerated]
internal class Program
{
private static void <Main>$(string[] args)
{
Ty[] array = new Ty[0];
Ty.Tuple tuple = new Ty.Tuple();
}
}
It does not assign a new array to Of It works if I do Of = [] though
Ty[] tys = { };
var tup = new Ty.Tuple { Of = [] };
Ty[] tys = { };
var tup = new Ty.Tuple { Of = [] };
generates
[CompilerGenerated]
internal class Program
{
private static void <Main>$(string[] args)
{
Ty[] array = new Ty[0];
Ty.Tuple tuple = new Ty.Tuple();
tuple.Of = Array.Empty<Ty>();
Ty.Tuple tuple2 = tuple;
}
}
[CompilerGenerated]
internal class Program
{
private static void <Main>$(string[] args)
{
Ty[] array = new Ty[0];
Ty.Tuple tuple = new Ty.Tuple();
tuple.Of = Array.Empty<Ty>();
Ty.Tuple tuple2 = tuple;
}
}
So the easiest solution would be upgrade to .NET 8 and use [] Far as explanation goes, no idea
ABp16
ABp16OP8mo ago
Now I have to look for this little thing everywhere in my codebase I used it a bunch x) Do you know anyone who might have one ? I'm just curious
Angius
Angius8mo ago
Huh, there are some MS people from the language and compiler team on the server
ABp16
ABp16OP8mo ago
I think it might be related to this syntax
No description
Angius
Angius8mo ago
Might be {} can, contextually, be an object initializer not an array initializer While [] is always a collection initializer
ABp16
ABp16OP8mo ago
Do they have a specific role / is there someone who is open to be pinged ?
Angius
Angius8mo ago
No such role, alas
ABp16
ABp16OP8mo ago
I thought it should be preceded by "new" if it's an object initializer
Angius
Angius8mo ago
I'll post it in the associates channel, though
ABp16
ABp16OP8mo ago
and it's weird that it just gives null Alright thank you! Thank you for your time as well there seems to be a verified microsoft employee role but I think it might be best not to ping them directly
Angius
Angius8mo ago
@mtreit? :when:
ABp16
ABp16OP8mo ago
Oh well x)
Angius
Angius8mo ago
Care to weigh in?
mtreit
mtreit8mo ago
What are we discussing? Haven't scrolled up.
ABp16
ABp16OP8mo ago
reason those two
Ty[] tys = {};
Console.WriteLine(tys.Length); // This is fine

// Of is a Ty[]
var tup = new Ty.Tuple { Of = {} };
Console.WriteLine(tup.Of.Length); // This causes a null pointer exception
Ty[] tys = {};
Console.WriteLine(tys.Length); // This is fine

// Of is a Ty[]
var tup = new Ty.Tuple { Of = {} };
Console.WriteLine(tup.Of.Length); // This causes a null pointer exception
are different
mtreit
mtreit8mo ago
Good question, I don't think I've ever used that syntax.
Aaron
Aaron8mo ago
Thing = {} in an object initializer is the syntax for adding things, not creating a collection for example
MODiX
MODiX8mo ago
Aaron
REPL Result: Failure
class C
{
public List<int> List { get; set; }
}
new C() {
List = { 1, 2, 3, 4 }
}
class C
{
public List<int> List { get; set; }
}
new C() {
List = { 1, 2, 3, 4 }
}
Exception: NullReferenceException
- Object reference not set to an instance of an object.
- Object reference not set to an instance of an object.
Quoted by
<@270457259065081856> from #taxed-void (click here)
Compile: 283.852ms | Execution: 60.462ms | React with ❌ to remove this embed.
Aaron
Aaron8mo ago
the list is null, it tries to do List.Add, and throws
ABp16
ABp16OP8mo ago
Ty[] tys = {};
Console.WriteLine(tys.Length); // This is fine
Ty[] tys = {};
Console.WriteLine(tys.Length); // This is fine
It works on arrays though
Aaron
Aaron8mo ago
thats not in an object initializer though thats where the difference exists the syntax means something different in a difference place
ABp16
ABp16OP8mo ago
Ah, I figured it was something like that
Aaron
Aaron8mo ago
if you want to create the collection, use [] instead of {}
ABp16
ABp16OP8mo ago
Well, apparently that's in dotnet 8.0, I haven't upgraded to that yet I'm using Array.Empty now
Angius
Angius8mo ago
Just switch the number Upgrade to 8.0 should literally be just it
Aaron
Aaron8mo ago
that is also fine
Angius
Angius8mo ago
No other changes required
ABp16
ABp16OP8mo ago
don't I need to install it though
Angius
Angius8mo ago
And that is not a problem either
Aaron
Aaron8mo ago
besides, yknow, the list of changes required https://learn.microsoft.com/en-us/dotnet/core/compatibility/8.0
Breaking changes in .NET 8
Navigate to the breaking changes in .NET 8.
Angius
Angius8mo ago
Those are few and mostly to obscure APIS, IME winget install --id Microsoft.DotNet.SDK.8
ABp16
ABp16OP8mo ago
Alright alright fine I'll do it now x)
Angius
Angius8mo ago
Alternatively, if you use VS, chances are the SDK should be installed with it dotnet --list-sdks will answer that question
ABp16
ABp16OP8mo ago
I use Rider It didn't seem to be installed yet
Angius
Angius8mo ago
Ah Then yeah, install it with Winget
ABp16
ABp16OP8mo ago
Well, thank you all for your help Much appreciated !
Want results from more Discord servers?
Add your server