public è visibile ovunque.
internal è visibile solo all'interno di un assieme
Tendi a usare interno solo per proteggere le API interne. Ad esempio, potresti esporre diversi overload di un metodo:
public int Add(int x, int y)
public int Add(int x,int y, int z)
Entrambi chiamano il metodo interno
internal int Add(int[] numbers)
È quindi possibile applicare molta raffinatezza a un metodo, ma "proteggerlo" utilizzando metodi di facciata che possono aiutare il programmatore a chiamare correttamente il metodo. (Il metodo di implementazione con il parametro array può avere un limite arbitrario di valori, ad esempio.)
Vale anche la pena notare che usando Reflection, tutti i metodi sono richiamabili indipendentemente dalla loro visibilità. Un altro "hack" per controllare / ottenere l'accesso alle API nascoste internamente.