问题
Consider the following classes:
public abstract class Token
{
    private List<Token> _Tokens { get; set; }
    // ReadOnly public is mandatory. How to give protected add-only, index-based access?
    public ReadOnlyCollection<Token> Tokens { get { return (this._Tokens.AsReadOnly()); } }
    // AddOnly for derived classes.
    protected Token AddToken (Token token) { this._Tokens.Add(token); return (token); }
}
public class ParenthesesToken: Token
{
    // This method is called frequently from public code.
    public void Parse ()
    {
        // Good enough.
        base.AddToken(...);
        // Is a call to List<T>.AsReadOnly() necessary?
        // Add-only, indexed-based access is mandatory here. IEnumerable<T> will not do.
        foreach (var token in this.Tokens) { /* Do something... */ }
    }
}
Is there something about the interfaces implemented by List and ReadOnlyCollection that would allow one-way type casting rather than recreating of the list to other concrete implementations?
The objective is to allow public read-only access but also protected add-only, indexed-based access to derived classes.
回答1:
public abstract class Token
{
    private List<Token> _tokens { get; set; }
    public IEnumerable<Token> Tokens 
    { 
       get { return _tokens; } 
    }
    protected Token AddToken (Token token) 
    { 
       _tokens.Add(token); 
       return token; 
    }
    protected Token GetTokenAt(int index)
    {
        return _tokens[index];
    }
}
I don't like returning read-only collections, because IEnumerable is a read-only interface which hides implementation from consumer. Some can argue, that consumer may cast IEnumerable to list and add new items, but that means two things:
- consumer violates API you provided
- you can't stop consumer from reflection usage
来源:https://stackoverflow.com/questions/20880941/private-listt-with-public-ienumerablet-vs-readonlycollectiont