Ti devi mettere dal punto di vista di chi scrive una classe di libreria, cioe una classe che potrà essere usata in progetti diversi con esigenze diverse.
Supponi di scrivere una classe che fa quasi tutto quello che deve fare tranne qualche aspetto essenziale che potrebbe essere fatto in modi diversi.
Ad esempio, protresti creare una classe che manipola in qualche modo dei dati (ad esempio un elenco di utenti) e che fornisce un mucchio di funzioni utili, però non specifichi come questi dati vengono ottenuti, ad esempio in un progetto vorresti leggere un database, in un altro leggre un file di testo, in un terzo preferisci il file XML ecc. In questo caso lasci astratto il metodo che si occupa della lettura ed in ogni progetto derivi una classe specifica, ad esempio:
abstract class MyUsers
{
protected List<string> m_users = new List<string>();
protected abstract void LoadUsers();
public string GetUserList()
{
StringBuilder sb = new StringBuilder();
foreach (string s in m_users)
{
sb.AppendLine(s);
}
return sb.ToString();
}
public bool UserExists(string name)
{
foreach (string s in m_users)
{
if (s == name)
return false;
}
return true;
}
// ecc.
}
class MyUsersVersion1: MyUsers
{
protected override void LoadUsers()
{
// apro un database e con una query ottengo la lista degli utenti
}
}
class MyUsersVersion2 : MyUsers
{
protected override void LoadUsers()
{
// apro un file di testo e leggo la lista degli utenti
}
}
In un caso del genere la classe base potrebbe anche non essere stata astratta e il metodo LoadUsers essere semlicemente virtuale o voto o con una implementazione qualsiasi. Però una classe del genere potrebbe sarebbe pressoche inutile, rendendola abstract impedisci che l' utente la istanzi per sbaglio e la usi in maniera errata.
Nel NetFramework molte classi di libreria sono astratte ad esempio TextReader, DbConnection, XmlNode ecc.