Should accessible members of an internal class be internal too?

I’m designing a set of APIs for some applications I’m working on. I want to keep the code style consistent in all the classes I write but I’ve found that there are a few inconsistencies that I’m introducing and I don’t know what the best way to resolve them is.

My example here is specific to C# but this would apply to any language with similar mechanisms.

There are a few classes that I need for implementation purposes that I don’t necessarily want to expose in the API so I make them internal whereever needed.

Generally what I would do is design the class as I normally would (e.g., make members public/protected/private where necessary) and change the visibility level of the class itself to internal. So I might have a few classes that look like this:

internal interface IMyItem
{
    ItemSet AddTo(ItemSet set);
}

internal class _SmallItem : IMyItem
{
    private readonly /* parameters */;
    public _SmallItem(/* small item parameters */) { /* ... */ }

    public ItemSet AddTo(ItemSet set) { /* ... */ }
}

internal abstract class _CompositeItem: IMyItem
{
    private readonly /* parameters */;
    public _CompositeItem(/* composite item parameters */) { /* ... */ }

    public abstract object UsefulInformation { get; }
    protected void HelperMethod(/* parameters */) { /* ... */ }
}

internal class _BigItem : _CompositeItem
{
    private readonly /* parameters */;
    public _BigItem(/* big item parameters */) { /* ... */ }

    public override object UsefulInformation
    {
        get { /* ... */ }
    }

    public ItemSet AddTo(ItemSet set) { /* ... */ }
}

In another generated class (part of a parser/scanner), there is a structure that contains fields for all possible values it can represent. The class generated is internal too but I have control over the visibility of the members and decided to make them internal as well.

internal partial struct ValueType
{
    internal string               String;
    internal ItemSet              ItemSet;
    internal IMyItem              MyItem;
}

internal class TokenValue
{
    internal static int EQ(ItemSetScanner scanner) { /* ... */ }
    internal static int NAME(ItemSetScanner scanner, string value) { /* ... */ }
    internal static int VALUE(ItemSetScanner scanner, string value) { /* ... */ }
    //...
}

To me, this feels odd because the first set of classes, I didn’t necessarily have to make some members public, they very well could have been made internal. internal members of an internal type can only be accessed internally anyway so why make them public? I just don’t like the idea that the way I write my classes has to change drastically (i.e., change all uses of public to internal) just because the class is internal.

Any thoughts on what I should do here?

It makes sense to me that I might want to make some members of a class declared public, internal. But it’s less clear to me when the class is declared internal.

2

As far as C# specification is concerned, there is no difference when you make a method internal or public so long as the type that holds it is internal. The only consideration might be that if you were to make the class public in the future, whichever methods you are likely to make public then, you could do that now. However, you may find differences of opinion even on this topic.

It comes to a matter of preference on your part (and your team) and I doubt that you may even get an agreement within your team if it’s more than a few developers, let alone on a community as broad as this.

In addition, these preferences work well for any new code being written, but for any existing code, there is no benefit to justify the cost of changing the code (except for developer’s own sanity). I have seen code written in both styles, even within the same project by two different developers.

As for the specification, pertinent parts of section 3.5.2 (p. 61) of C# 5.0 language specification states the following (and I believe it is the same in previous versions too):

The accessibility domain of a nested member M declared in a type T
within a program P is defined as follows (noting that M itself may
possibly be a type):

  • If the declared accessibility of M is public, the accessibility domain of M is the accessibility domain of T.
  • If the declared accessibility of M is internal, the accessibility domain of M is the intersection of the accessibility domain of T with
    the program text of P.

Since accessibility domain of T in your case is internal, so accessibility domain of M is the same regardless of it being internal or public.

just make sure that in your given language there is no what I’ll call “side channel” through which consumers of your api could access a public member of an internal class, because if there is, and they find it and use it, that part of your code is “as good as” public api from then on. That means they scream if you change it and you get stuck supporting it.

In Java one example of a side channel is reflection. Devs can and have used it to gain access to members which the api author never intended they should know about.

1

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật