posts - 644, comments - 2003, trackbacks - 137

My Links

News

Raffaele Rialdi website

Su questo sito si trovano i miei articoli, esempi, snippet, tools, etc.

Archives

Post Categories

Image Galleries

Blogs

Links

Un comodo effetto collaterale degli extension method

Non bisogna mai dimenticare che un extension method è sempre e solo un metodo statico a cui passiamo un oggetto come primo parametro.

Prendiamo in esame un banale (ed inutile) esempio di extension method:

namespace Raf.Extensions { public static class StringExtensions { public static char GetFirstChar(this string text) { return text[0]; } } }

Per usarlo, dovremo solo referenziare il namespace con "using" ed invocarlo come fosse un metodo della classe string

using Raf.Extensions; /* ... */ private void test(string text) { Console.WriteLine(text.GetFirstChar()); }
using Raf.Extensions; /* ... */ p.test("Hello, world"); /* ... */ private void test(string text) { Console.WriteLine(text.GetFirstChar()); }

Appare immediatamente chiara la necessità di gestire il caso in cui la stringa valga null o sia di lunghezza zero. In questa eventualità è quindi necessario introdurre un controllo e decidere il valore da stampare.

Se GetFirstChar fosse un metodo membro della classe, il controllo andrebbe necessariamente fatto esternamente, altrimenti il null farebbe esplodere un'eccezione.

Nel caso di un'extension method questo non è vero e quindi potremmo riscrivere il tutto in questo modo:

namespace Raf.Extensions { public static class StringExtensions { public static char GetFirstChar(this string text) { if (string.IsNullOrEmpty(text)) return ' '; return text[0]; } } }

Il non-intuitivo, seppur comodissimo codice, sarebbe il seguente:

using Raf.Extensions; /* ... */ p.test(null); /* ... */ private void test(string text) { Console.WriteLine(text.GetFirstChar()); }

A vedere questo codice mi verrebbero i capelli dritti perché senza extension method la NullReferenceException sarebbe scontata e invece tutto funziona come desiderato.

 

Prima di giudicare terrificante questo side-effect, veniamo ad un esempio più utile di quello appena visto.
Diciamo di voler eseguire il parsing di un file xml dove l'attributo "Name" è opzionale. Potremmo scrivere un extension che ha il duplice scopo di eseguire il controllo dell'assenza dell'attributo e fornire allo stesso tempo il valore di default (stringa vuota).

namespace Raf.Extensions { public static class XAttributeExtensions { public static string GetString(this XAttribute attribute) { if (attribute == null) return string.Empty; return attribute.Value; } } }

using Raf.Extensions; /* ... */ var xml1 = new XElement("root", new XAttribute("Name", "Raf")); // <root Name="Raf" /> var xml2 = new XElement("root"); // <root /> p.PrintName(xml1); p.PrintName(xml2); /* ... */ private void PrintName(XElement xml) { var name = xml.Attribute("Name").GetString(); Console.WriteLine(name); }
Sono certo che molti storceranno il naso davanti a codice come questo, ma se anche non è vostra intenzione avvalervene, è bene essere coscienti che il linguaggio lo permette e che è comunque codice davanti al quale potremmo sempre trovarci davanti.

Print | posted on lunedì 14 febbraio 2011 16:06 |

Feedback

Gravatar

# re: Un comodo effetto collaterale degli extension method

@Luca. Come ho scritto a me piace, ma l'aspetto meno piacevole è che la sintassi non è intuitva e se vogliamo è pure ingannevole.
Riprendendo l'esempio del post, quando ti trovi davanti a questo codice:
XAttribute attr = null;
var name = str.GetString("Nome");
ti aspetti un'eccezione. Non conosco altri linguaggi oop che funzionerebbero in questo caso.
La comodità di sganciarsi dal controllo dei null è comunque impagabile per chi come il sottoscritto è un tifoso di Spec# :)
14/02/2011 20:05 | Raffaele Rialdi
Gravatar

# re: Un comodo effetto collaterale degli extension method

Anch'io ho trovato comodo sfruttare tale possibilità per definire un extension method di object che mi permette di valutare se un riferimento è null. Così posso scrivere condizioni del tipo:
if (obj.IsNull())
{
...
}
else
{
...
}
Ok, non fa gran differenza rispetto a testare object.ReferenceEquals(obj, null), ma è più breve...
Ah già in C# c'è anche l'operatore ==, ma quella è un'altra storia (lunga).
14/02/2011 20:25 | Federico
Gravatar

# re: Un comodo effetto collaterale degli extension method

Verissimo. Però se il codice così è scritto in un progetto personale ben venga.
Se mi capita però di vederlo in codice che "shippa" garantisco che l'autore verrà spellato vivo, messo sotto sale e esposto al pubblico lubidrio.
14/02/2011 20:38 | Paperino
Gravatar

# re: Un comodo effetto collaterale degli extension method

@Raffaele: al tuo post! Sono stato addestrato dai Code Nazi. E ho detto tutto (cit.)
15/02/2011 20:06 | Paperino
Gravatar

# re: Un comodo effetto collaterale degli extension method

@Paperino :) Vorrei capire meglio le motivazioni.
Nel caso degli XAttribute, quando ne hai decine e decine, fa una bella differenza anche sulla leggibilità che spesso è direttamente proporzionale al numero di casini che ci puoi trovare dentro.
16/02/2011 00:45 | Raffaele Rialdi
Gravatar

# re: Un comodo effetto collaterale degli extension method

> Riprendendo l'esempio del post, quando ti trovi davanti a questo codice:
> XAttribute attr = null;
> var name = str.GetString("Nome");
> ti aspetti un'eccezione

...a meno che il nome del metodo non ti dia da subito segnali sul contrario, magari approfonditi nel summary. ;-)
Es. GetStringHandlingNull o qualcosa del genere.
21/02/2011 01:14 | Mario Duzioni
Comments have been closed on this topic.

Powered by:
Powered By Subtext Powered By ASP.NET