views:

241

answers:

6

I just want to understand why I cannot create a protected enum on C#?

The compiler refuses to accept that

Does anyone know why that may be?

+6  A: 

You can create an enum with protected access modifier if it's a nested type. Types created directly in a namespace can only assume public and internal access modifiers. It doesn't make sense to create a private, protected, or protected internal type directly in a namespace since you wouldn't be able to use it anywhere (since you can't inherit from a namespace or declare methods in it).

Mehrdad Afshari
+11  A: 

You can have a protected type which is nested within another type - and that includes enums:

public class Outer
{
    protected enum NestedEnum { Foo, Bar, Baz };
}

However, it doesn't make sense to make a non-nested type protected - the protected modifier is about granting access to a member from within a derived type; as a top level type is only a member of a namespace rather than another type, there's no type you could derive from to get the extra access.

Could you describe what you're actually trying to achieve, and then we could try to work out what the most appropriate visibility would be?

Jon Skeet
Thanks - But why is that? Why can a class be protected and an enum not (at top leve)
ChloeRadshaw
I want to create an enum which can be extended by subclasses
ChloeRadshaw
Enums can't be extended in C#/.NET - they are derived from System.ValueType, and so, similar to structs, you can't inherit off them.
thecoop
@ChloeRadshaw: Two things: First, enums are not inheritable - only classes are. You can't derive one enum from another in C#. Second, you can't mark anything as `protected` at the top level - not even classes. The protected modifier is only used within a class to indicate that a member of that class is accessible to both the class and derived classes but not by any other code. At a namespace level, you can only mark things as `public` or `internal` - you are simply stating whether the type is visible outside the assembly or not.
LBushkin
@LBushkin: Are you sure about that? This compiles finenamespace ConsoleApplication1{ protected class CsvReader { }}
ChloeRadshaw
@ChloeRadshaw: No, that *doesn't* compile fine: "Test.cs(4,50): error CS1527: Elements defined in a namespace cannot be explicitly declared as private, protected, or protected internal."
Jon Skeet
I am now thoroughly confused - I am using VS2008 This works for me . using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace ConsoleApplication1{ protected class CsvReader { }}
ChloeRadshaw
+1  A: 

Can you post your code. I checked it on VS2008 and it worked.

Janko R
+1  A: 

Are you sure that you are not declaring outside a class?

Inside a class it works fine but you cannot declare a member protected because there is nothing to derive from. If it is defined inside a class it can be derived from and it can be accessed.

A protected enum outside a class definition would not be accessible from anywhere

Oskar Kjellin
+1  A: 

Nested enum could be 'protected'.

class Test { protected enum MyEnum { type1, type2 } }

ydobonmai
+3  A: 

The protected modifier is only meaningful in the context of a class declaration - it establishes that the item marked as protected is accessible to the class an it's derived classes, but not outside of the class.

If your enum is a nested enum of a class, it can be declared as protected.

However, if it is a top-level enum, it can be either public or internal. Public, of course, means it is visible to everyone both inside and outside the assembly. Internal means it is only visible within the assembly. Perhaps internal is what you are looking for.

EDIT: Enum values are not inheritable in C# - the only purpose to allow this would be to be able to add additional values to the enum. While it's not possible with enums, we can use the typesafe enum pattern similar to Java's to do this:

public class BaseEnum 
{
    private readonly int m_Value;

    protected BaseEnum( int val ) { m_Value = val; }

    public static readonly BaseEnum First  = new BaseEnum(1);
    public static readonly BaseEnum Second = new BaseEnum(2);
    public static readonly BaseEnum Third  = new BaseEnum(3);
}

public class DerivedEnum : BaseEnum
{
    protected DerivedEnum( int val ) : base( val ) { }

    public static readonly DerivedEnum Fourth = new DerivedEnum(4);
    public static readonly DerivedEnum Fifth  = new DerivedEnum(5);
}
LBushkin
Indeed internal does work but I dont get why you cant extend an enum at naespace level
ChloeRadshaw
By 'extend' do you mean create a derived enum? This is not possible because Enums are a special kind of value type and value types cannot be inherited.
Dan Bryant
@ChloeRadshaw: Enums are not inheritable - you can't derive one enum from another. They are simply a convenient way to provide names for a set of values.
LBushkin
@LBushkin: +1 Fascinating example of a 'typsafe enum' : curious in what real-world scenario you would make use of such a "chimera" ?
BillW
I really like that approach sadly this gets rid of the `const` -ness of the enum and as such renders it unusable for `switch` statements.
Florian Doyon