C # não é a única linguagem de programação para .NET; outros idiomas podem e têm acessibilidade padrão diferente em vários contextos. A especificação privatedeixará claro para quem ler o código que essa acessibilidade é pretendida, enquanto a omissão da especificação deixa em aberto a questão de saber se o membro pode ter sido, por exemplo, destinado a ser usado dentro do assembly [como seria o padrão no VB.NET] . Ser explícito pode ser especialmente útil se você usar vários idiomas com regras diferentes.
Com relação a se deve privateou protectednão ser favorecido na ausência de um argumento particularmente convincente a favor do outro, a decisão deve se basear em se é mais provável que a exposição de um membro torne possível a uma classe derivada fazer algo útil que caso contrário, não seria possível ou impediria que versões futuras de uma classe modificassem suas estruturas de dados internas de uma maneira que fosse mais eficiente. Pode-se ver exemplos de ambas as situações em List<T>.
Em alguns casos, se houver uma lista de agregados (por exemplo, Pointestruturas), pode ser útil atualizar itens no local. Se List<T>exposto seu armazenamento de suporte a classes derivadas, pode-se definir facilmente um EditableList<T>com um método:
delegate void ActByRef<T1,T2>(ref T1 p1, ref T2 p2);
void ActOnItem<TParam>(int index, ref TParam param, ActByRef<TParam> proc)
{
.. test index, then...
proc(ref _arr[index], ref proc);
}
que poderia então ser chamado usando algo como:
int adjustmentAmount = ...;
myList.ActOnItem(index, ref adjustmentAmount,
(ref Point pt, ref int dx) => pt.X += dx );
Esse método pode permitir atualizações eficientes, mesmo com tipos de estrutura relativamente grandes [já que nenhuma cópia seria necessária]. O fato de List<T>não expor seus componentes internos torna impossível derivar uma classe que poderia implementar esse operador com eficiência.
Por outro lado, embora, até onde eu saiba, a Microsoft ainda não tenha explorado essa capacidade, ter o armazenamento secundário privado tornaria possível para uma versão futura List<T>dividir o armazenamento secundário em partes menores que 85K ao usar a maioria dos dados. tipos ou menores que 1000 itens ao usar double. Essa divisão não seria possível se List<T>houvesse exposto o armazenamento de suporte a classes derivadas.