2013-08-02 18 views
6

Mi chiedo questo, dal momento che ho bisogno di ereditare da StringBuilder per implementare un evento TextChanged. Potrei sempre creare un wrapper contenente un private StringBuilder e conversioni implicite/esplicite, ma questa non sembra una soluzione adeguata.Perché la classe StringBuilder è sigillata?

Fortunatamente posso ereditare dall'oggetto che sta scrivendo su StringBuilder, quindi questo non è un problema per me, ma sono ancora curioso di sapere perché quella classe sia sigillata.

+2

Perché è necessario gestire un evento "TextChanged" di StringBuilder? Tu sei colui che aggiunge del testo ad esso. Presumo che le considerazioni sulle prestazioni superino la loro estensibilità. –

+0

@Tim Cosa succede se è un 'StringWriter' o una funzione nativa come' SendMessage'? Inoltre, gli eventi sono generalmente più piacevoli con cui lavorare che scrivere codice come "void WriteToBuilder (StringBuilder sb, string text)". – KappaG3

+2

["Progettare e documentare per ereditarietà o altrimenti vietarlo"] (http://martinfowler.com/bliki/DesignedInheritance.html) – dasblinkenlight

risposta

12

Questo è un po 'difficile da rispondere. La risposta di upvoted ha un problema, StringBuilder non ha metodi virtuali. Quindi non c'è niente che tu possa fare a interrompere la classe o fare qualcosa di "extra" non sicuro.

Penso che la ragione probabile sia che il CLR ha una conoscenza speciale della classe. Questo è un po 'banale per StringBuilder, rispetto ad altri tipi di .NET con cui è intimo, il marshaller di pinvoke sa come si presenta la classe. Lo si utilizza quando è necessario passare un riferimento di stringa al codice non gestito, consentendogli di scrivere il contenuto della stringa. Necessario perché non è legale per String, è immutabile. Il marshaller pinvoke sa come impostare correttamente i membri interni di StringBuilder dopo la chiamata a pinvoke. Ma non saprei come farlo per la tua classe derivata. Questo rischio di taglio non vale esattamente il vantaggio di non sigillarlo. Soprattutto perché non ha metodi virtuali quindi non è possibile ignorare il suo comportamento.

Un metodo di estensione è altrimenti una soluzione molto ragionevole.

+0

potrebbe non avere nulla di virtuale ma ha qualcosa di molto peggio ... direttamente i membri pubblici che sono contrassegnati come 'internal', non sono sicuro di come il CLR potrebbe risolvere il problema ... o se impedirebbe a una classe derivata di modificare loro. – Mgetz

+0

Questo è qualcosa * molto * diverso, significa solo che il metodo è implementato in C++ anziché C#. Backgrounder [è qui] (http://stackoverflow.com/questions/8870442/how-is-math-pow-implemented-in-net-framework/8870593#8870593) –

+0

Suoni "StringBuilder non ha alcun metodo virtuale" un po 'sbagliato. Ogni oggetto include metodi virtuali per equals/hashcode e l'override di questo (specialmente per la stringa) può causare l'arresto di tutto il sistema. –

6

StringBuilder è sigillato perché assembla stringhe, ad es. non ci dovrebbe mai essere una ragione per ereditarlo perché ogni uso dovrebbe essere limitato nella portata. StringBuilder non è un sostituto per string e non dovrebbe mai essere utilizzato in questo modo. L'obiettivo della classe era di avere un modo di gestire facilmente qualsiasi operazione che richiedesse stringhe mutabili senza penalizzazione delle prestazioni. In questo modo non è possibile ereditare da StringBuilder fornire alcuna utilità e creerebbe possibili problemi di sicurezza poiché la classe si occupa di stringhe mutabili.

Dai uno sguardo allo reference source non è una classe semplice ma un'utilità strettamente focalizzata. Inoltre fa cose che sono unsafe, e quindi consentendo l'ereditarietà consentirebbe la modifica di codice non sicuro che potrebbe compromettere la sicurezza.

+1

Vedo. Ma poi di nuovo, non potrebbero semplicemente sigillare * le cose pericolose da scavalcare *? Non è necessario sigillare completamente la classe. Inoltre, la maggior parte dei suoi membri sembra essere interna, quindi ereditare non li mostrerebbe nemmeno. – KappaG3

+0

@ KappaG3 hai dato un'occhiata alla classe ... "non sicuro" è utilizzato in quasi tutte le funzioni. L'obiettivo era la rapidità con la sicurezza, non l'extensiblilty come si supponeva (abbastanza correttamente perché non ho ancora visto un caso d'uso) che nessuno avrebbe mai avuto bisogno di estenderlo. – Mgetz

+4

@ KappaG3: perché 'StringBuilder' è destinato a utilizzare all'interno dei metodi per risolvere compiti particolari - costruisci una stringa qui e ora. Non dovrebbe nemmeno far parte del contratto pubblico di alcun tipo. – Dennis

Problemi correlati