What is default accessibility modifier for struct Point in my code?
I am trying to determine whether struct Point is public or internal. It could also be private since the intellisense shows Point
as a member of UserQuery class.
And also what is the accessibility modifier of Main method?
Comments
Both private.
Remove the Extension Method that won't compile and reflect in ILSpy (Alt-Shift-R) to confirm this.
The short answer is that they are both private. So, in your scenario, you must add an internal or public modifier the Point type.
The long answer is that LINQPad normally wraps your code in a class called UserQuery. (This is analogous to the way that the C# compiler wraps top-level statements in a method and class.)
This means that types that you write - such as PointExtensions - are nested within UserQuery. This is usually ideal, because PointExtensions can access members of the containing type without you needing to add accessibility modifiers.
However, C# has a peculiar restriction when it comes to extension methods. That is, that they can't reside in nested types. Obviously LINQPad knows this, and it isn't going tell you that you can't run your code, so it moves static classes that contain extension methods out of UserQuery so that they're not nested and compile. They can still see nested types in UserQuery (thanks to a static using) - but now those members require an internal or public access modifier in order to be accessible.
Another interesting footnote is that you can force LINQPad to make all type declarations non-nested with the
#LINQPad nonest
directive. This can be useful in various other edge-cases.The following code made it work. It compiled and even ran successfully.
Please take a look at the screenshot in the post submitted a few minutes ago.
It seems that struc Point and static class PointExtensions are private and nested types OR is the struc Point nested but static class PointExtensions is not nested since LINQPad has behind the scenes pulled it out of the UserQuery class when LINQPad ran the code?
The exact code that worked in LINQPad is as below.
Ah, you must be running LINQPad 5. This is more heavy-handed, and will also extract the Point struct in this scenario (because it's required by your extension method). This is why you've ended up with no nested types.
The level of auto-magic was stepped down in LINQPad 6/7/8, to make its behavior more easily predictable. In LINQPad 6/7/8, it only unnests types that it absolutely has to (i.e., static classes containing extension methods) - unless you use the
#LINQPad nonest
directive (in which case it unnests everything).Also, in LINQPad 7/8, you can disable all auto-magic as follows, if you want to investigate C#'s normal accessibility rules without nested types:
The version of LINQPad I have is 4.59.00
OK, so that's cool if LINQPad is unnesting the types as per the situation. That means, ultimately these types in my code are becoming internal or public. Is that right?
I used your sample code in the last post and the namespace part had to be removed since LINQPad complained "Invalid token 'namespace' in class, struct, or interface member declaration", after which it worked.
Also, when I put the directive #LINQPad nonest at the start of my code, LINQPad complained "Single-line comment or end-of-line expected". However, when I instead put the directive #define NONEST then LINQPad compiled successfully, but I'm not sure if its doing the same job of unnesting the types.
The types accessibility will remain internal (the default). LINQPad does not change the accessibility of any of your types.
I don't think 4.59 supports the
nonest
option, nor the ability to define namespaces.