In C#, a nested class (including its static and non static methods) can access all static and non-static members and methods of an object of the type of the outer class, including the outer class itself, regardless of the protection level. The protection level only matters when accessing it from outside of the nested or outside of the outer class.
You cannot access the non-static members and methods of the outer class on an object of the type of the nested class, regardless of the protection level (it is not possible even if it is being accessed in the outer class or the nested class or another class entirely); you have to use an outer class object. Similarly, you cannot access the static members and methods of the outer class via the nested class name, you have to use the outer class name.
An outer class cannot access private members (static or non-static) of the nested class (via an object of the type of the nested class or via the nested class itself), but it can instantiate the class because the class type of the nested class itself is always accessible to the outer class. This means if the nested class is private but a static member is not private then it will be able to access the member, but if the member is private then it won't be able to access the member. In this instance accessing from the outer class is like accessing from another class in the assembly entirely.
You cannot access the non-static members and methods of the nested class on an object of the type of the outer class, regardless of the protection level; you have to use an inner class object. Similarly, you cannot access the static members and methods of the nested class via the outer class name, you have to use the inner class name.
In C#, the outer and nested class objects are always instantiated as separate objects, but you can place a reference to the outer class in the nested class and a reference to the nested class in the outer class.
In Java, the nested class is called an inner class if it is not static. An inner and outer class are instantiated separately but you need to use the outer object in order to instantiate the inner object, meaning that the inner object is always associated with an outer object. This means that you need to instantiate an outer object first. The inner object is however not a member of the outer object and the outer object is not a member of the inner object, so you have to explicitly make it one in order to be able access the object that it is paired with outside of the class. Inside the inner class however, you can access all outer object members and methods using outerclass.this.method using the special version of this – as you need this to do it, you can't access it outside of the inner class. Inside the outer class, you cannot access the inner object tied to an outer object using innerclass.this.method2 as the special this is used to get the outer object of the this object only. This is because an outer object can have many inner objects, so it would be ambiguous and is disallowed.
Another difference between Java and C# is the fact that you can access private inner members from within the outer class via an object of the type of the inner class (as paragraph 3 mentioned) in Java.
Another difference between Java and C# is that a static nested class in Java is different to the static nested classes of other languages like C++ and C#, for which there is no equivalent in Java. A static nested class in Java is a regular nested class in C# – It just removes the requirement that the nested class needs to be instantiated using an object of the outer class, instead an object of the outer and nested class can be instantiated separately, and hence the special this does not work either.
static classhas quite different meanings in the two languages (and, thus, what a non-staticclassmeans). This comes into play in inner classes. You might want to look upstatic classin each context to help it make sense.