views:

132

answers:

4

After a little research I've determined that the only access modifiers which you can apply to classes are:

  • public - available in any assembly
  • internal - available only in the current assembly

but the error message below seems to imply that if a class is not defined in a namespace that it could be defined as private, protected, or protected internal.

Are public and internal the only class modifiers you can use on class or are there more?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Test2343434
{
    class Program
    {
        static void Main(string[] args)
        {
            Tools.ToolManager toolManager = new Tools.ToolManager();

            Console.ReadLine();
        }
    }

}

namespace Tools
{
    //error: Elements defined in a namespace cannot be explicitly 
    //declared as private, protected, or protected internal
    private class ToolManager 
    {
        public ToolManager()
        {
            Console.WriteLine("inside tool manager");
        }
    }
}
+7  A: 

A nested type can be declared private, protected, or protected internal. You can still declare nested types as public or internal of course - it's just that you can only declare them with the above access modifiers when they're nested:

public class OuterClass
{
    private class PrivateNested {}
    protected class ProtectedNested {}
    protected internal class ProtectedInternalNested {}
    public class PublicNested {}
    internal class InternalNested {}
}

Note that you can't declare a type nested in a struct to be protected or protected internal because it doesn't make any sense to do so :)

public struct OuterStruct
{
    private class PrivateNested {}
    public class PublicNested {}
    internal class InternalNested {}
}

C# doesn't allow types to be nested in interfaces (unfortunately, IMO - it would be useful for code contracts).

All of this is true for other nested types (enums, structs, interfaces, delegates) too.

Jon Skeet
Definitely worth knowing about, as private nested classes can be quite useful.
Dan Bryant
Actually, according to MSDN, it can also be public or internal. What you said is true for structs.
Daniel Rose
The key point is that namespaces are *not* containers, while classes *are* containers. The possible access modifiers are determined by whether or not it's in a container (e.g., whether the class is a *member* or not).
Stephen Cleary
@Daniel: Yes, I wasn't trying to be exclusive... will edit.
Jon Skeet
@Stephen: Namespaces are containers of a sort: non-nested types are members of namespaces. From the C# spec: "A namespace-member-declaration is either a namespace-declaration (§9.2) or a type-declaration (§9.6)."
Jon Skeet
@Jon: My terminology could use work - all the good names are taken. :) The point was that programmers often fall into the trap of thinking of a namespace as being similar to a static class. I believe a more correct perception is that all top-level types are flat, and the namespace is just used as a name prefix. Once this mental adjustment is made, it becomes blindingly obvious *why* the only access modifiers possible for top-level types would be public and internal.
Stephen Cleary
+3  A: 

Take a look at this MSDN page:

Type declarations in a namespace can have either public or internal access. If no accessibility is specified, internal is the default.

It makes little sense for a type declaration in a namespace to be anything other than public to external assemblies, or internal (C# does not support the concept of friend classes or anything like that).

Kragen
I don't think the OP was asking about the default...
Jon Skeet
+3  A: 

The answer is found in Accessibility Levels.

A "top-level" class, i.e. not nested in another class, can only be public or internal. By default (if you don't declare anything), it is internal.

Nested classes can have all five possible accessibility levels, i.e. public, protected, internal, private, protected internal.

Daniel Rose
A: 

In the context of this question it might be interesting to point out that there is a not so well known mechanism for making internal classes visible to other assemblies. That mechanism is the InternalsVisibleTo attribute. It is not considered one of the access modifiers by any stretch, but does have the effect of manipulating who has access. The concept is referred to as friend assemblies.

Brian Gideon