jgorissen
jgorissen

Reputation: 23

Hide members of classes outside cs file, but accessible for classes within the file

If I have a cs file with 2 classes, and want to protect the members of my classes from the outside world, but let the classes have access to all members within the same file. Can this be done?

Guess I want the access modifier "internal" not te be working on the complete App_Code folder, but on this one file.

Simplified example:

public class Comments {
    private static List<CommentRecord> Records = new List<CommentRecord>();
    static Comments() {
        LoadFromDatabase();
    }

    public static void LoadFromDatabase() {
        // load and loop to fill data...
        CommentRecord comment = new CommentRecord();
        comment.Id = ...
        comment.ParentId = ...
        comment.Text = ...
        Records.Add(comment);
    }

    public static CommentRecord FindById(Int32 id) {
        return Records.Find(delegate(CommentRecord x){return x.Id == id;});
    }
}

public class CommentRecord {
    public Int32 Id = 0;
    public Int32 ParentId = 0;
    public String Text = "";

    public void Save() {
        // save...
    }
}

I do not want other outside classes to be touching the Id field, but the Comments class, in the same file, should be able to set it.

Upvotes: 1

Views: 543

Answers (2)

Peter Duniho
Peter Duniho

Reputation: 70652

Short answer: no, not possible.

You can get close by nesting the Comments class inside the CommentRecord class, where it would be able to access private members of the CommentsRecord class. But that's not a good solution unless you have some other valid reason to nest the class that way. If you don't, then you should just use internal, and accept that other code within the same project might be able to change it.

Even better IMHO would be make the field read-only (either as a field or property) and to not grant the Comments class access to the property setter. Instead, design the class as an immutable type and require the Comments class to pass the correct values to the constructor. Without more context it's impossible to know for sure whether that would work in your case, but it certainly would be a superior design.

Upvotes: 1

Michal Ciechan
Michal Ciechan

Reputation: 13888

What you want is a public interface, with a private inner class, so only Comments class can touch CommentsRecord.

public interface ICommentRecord
{
    int Id { get; }
    // Expose any other public members you want
}

public class Comments
{
    private static List<CommentRecord> Records = new List<CommentRecord>();
    static Comments()
    {
        LoadFromDatabase();
    }

    public static void LoadFromDatabase()
    {
        // load and loop to fill data...
        CommentRecord comment = new CommentRecord();
        comment.Id = 2;
        Records.Add(comment);
    }

    // Make this returnn the public interface
    public static ICommentRecord FindById(Int32 id)
    {
        return Records.Find(delegate(CommentRecord x) { return x.Id == id; });
    }

    // Make this class private to Comments class. So its only accessible from within Comments
    private class CommentRecord : ICommentRecord
    {
        public int Id { get; internal set; }  
    }

}

Your other option is to put your classes in a separate assembly, and use internal

Upvotes: 1

Related Questions