partial class and conditional compiling

Hi,
I have a following class declaration:

#if LOW_LEVEL
public sealed class Core
#else
internal sealed class Core
#endif
{

}
Based on the conditional compiling directive I want to control the access to the class. I do not define the LOW_LEVEL compiler directive (either in code or in project settings). I compile this class. It works fine.

But when the class definition is split across files like below:
//class1.cs
#if LOW_LEVEL
public partial sealed class Core
#else
internal sealed class Core
#endif
{
}

//class2.cs
#if LOW_LEVEL
public partial sealed class Core
#else
internal sealed class Core
#endif
{
}

and when I compile the two classes now I get the error: Partial declarations of Core have conflicting accessibility modifiers.

If i define the compiler directive LOW_LEVEL it compiles with out any errors. Why am I being forced to declare the conditional compiler directive If I do not define the symbol LOW_LEVEL I expect the class to be internal.

Any clarifications/explaining of whats going on here is much appreciated.

thanks,
SiWi





Answer this question

partial class and conditional compiling

  • SuriP

    Yes it compiles for me with our without LOW_LEVEL defined. Note however that partial has to precede class and not sealed. Note that partial types are not compiled in the same manner as other types. When the compiler decides to combine partial types into a single definition is pretty much up to it. This could, in theory, occur before or after the processor tokens are handled. Unlike other languages C# does not have a pre-processor phase from what I understand. Instead it handles the pre-processor tokens either on a per-file basis or inline during parsing. This means it could cause problems with partial types.

    Michael Taylor - 2/13/07
    http://p3net.mvps.org


  • DennisYang

    How are you going to get your internal class to compile You are basically defining Core in two different class files without a partial keyword. It shouldn't compile at all. The only way you'd get it to compile is to make it partial as well. Once you fix that it'll compile.

    Now however it is time to get on my soapbox. If one of my devs wrote this style of code then during code review we would have a long discussion on why this is a bad way to go and we'd redesign and code the application to resolve the issue. The first issue is conditional compilation. You are declaring a class to have two different accessibility options. Why This adds confusion with no gain in maintainability, performance or functionality. If you have a class that is generally publicly usable then mark it public. Create internal members of the class to hide members that are generally not callable. If, for whatever reason, there are a lot of internal members of the class then create two classes. One is public and the other internal. To avoid code duplication refactor the public class to use the internal class or create a third private class containing the implementation details and then have the public and internal classes rely on the private class. (Keep in mind a global type can't be private so I used the term private to distinguish the classes.) A better alternative is to expose the public class as an interface implemented by the internal class and exposed through a support class.

    The second problem I have is the use of partial. Partial type support was added almost strictly to help isolate user-generated code from machine-generated code. If you are using a partial type in your code to break up a large class then you need to consider refactoring your class into smaller pieces. The days of 100+ member classes (aka MFC) are over. It is considered poor design and makes maintenance harder. Break up large types into smaller subtypes and use inheritance to share functionality. You then have no use for partial types.

    Michael Taylor - 2/13/07
    http://p3net.mvps.org


  • SpeedOfSPin

    Hi Michael,

    Thanks for your reply.

    Sorry that was a typo in the first post. There is a partial keyword on both definitions. Otherwise the error message you get is a different one.

    Here's how they should be:
    //class1.cs
    #if LOW_LEVEL
    public partial sealed class Core
    #else
    internal partial sealed class Core
    #endif
    {
    }

    //class2.cs
    #if LOW_LEVEL
    public partial sealed class Core
    #else
    internal partial sealed class Core
    #endif
    {
    }

    I agree with your comments. This is not a ideal design technique. What I'm interested here is to find out why this code did not compile for me.

    Could you please confirm that you were able to compile the classes without errors when you put the partial keyword on the internal class definition and without defining the LOW_LEVEL symbol


    thanks,
    SiWi


  • partial class and conditional compiling