2011-01-10 27 views
34

Estoy buscando algunos pros y contras para usar métodos de extensión sobre las clases de utilidad estática en una aplicación C#.Métodos de extensión vs Static Utility Class

Por ejemplo, una ventaja en la columna de métodos de extensión es la conveniencia de llamar por el nombre de clase en lugar de algo así como "StringUtils". Pero una estafa sería que puede difuminar las líneas entre lo que está en el marco y lo que no.

+0

posible duplicar [evaluar los costos/beneficios de usar métodos de extensión en C# => 3.0] (http: // stackoverflow.com/questions/1644743/evaluation-cost-benefits-of-using-extension-methods-in-c-3-0) –

+0

Se publicó una pregunta similar aquí: http://stackoverflow.com/questions/487904/what- advantage-of-extension-methods-have-you-found Y aquí: http://stackoverflow.com/questions/1644743/evaluating-cost-benefits-of-using-extension-methods-in-c-3-0 – HABJAN

Respuesta

45

Yo diría que un pro es que borra las líneas entre lo que está en el marco y lo que no: puede usar su propio código tan naturalmente como código de marco, operando en tipos de marcos.

Los métodos de extensión no se deben usar arbitrariamente, por supuesto, no es como todos los métodos estáticos deben convertirse en métodos de extensión.

Intento pensar en ello como si el método lógicamente funciona "en" su primer parámetro. ¿Tendría sentido como método de instancia si pudieras incluirlo como método de instancia?

Un "con" que puede no conocer: si el tipo extendido más tarde agrega un método de instancia del mismo nombre que es aplicable con los mismos parámetros, su código de llamada comenzará a llamar a ese método de instancia la próxima vez recompilar Por ejemplo, Stream ganó CopyTo en .NET 4 ... Anteriormente había escrito un método de extensión CopyTo, que luego no se llamaría. No hay advertencia de que esto está ocurriendo, por lo que debe estar alerta.

Una advertencia: los métodos de extensión no han existido durante el tiempo suficiente para que las mejores prácticas se establezcan realmente. Debería sopesar todas las opiniones (incluso, o quizás especialmente, las mías) cuidadosamente.

+0

7 años después, ¿se han establecido las mejores prácticas? – Sipo

+1

@Sipo: No realmente :) –

10

Al final del día, ambos enfoques usan métodos estáticos. La única diferencia entre

string foo = "bob"; 
StringUtils.DoSomething(foo); 

y

string foo = "bob"; 
foo.DoSomething(); 

es el azúcar sintáctica. Se reduce a preferencias personales y estándares de codificación. A veces, el nombre del método puede ser lo suficientemente descriptivo como para no garantizar que se vea el nombre de la clase estática. Otras veces tiene más sentido incluir el nombre de la clase.

¡Finalmente, los métodos de extensión se pueden invocar también como métodos estáticos!

string foo = "bob"; 
StringExtensions.DoSomething(foo); 

Lo anterior utiliza el mismo código que en el segundo ejemplo, pero se invoca de manera diferente. Con este último tidbit en mente, podría crear clases de utilidad estáticas como métodos de extensión y luego invocarlas como lo desee.

+5

Como nota al margen: la sintaxis no es la única diferencia. Los métodos de extensión no usan conversiones implícitas, los métodos estáticos lo hacen. Es decir. 'long myLong; IntExtension.DoSomething (myLong) 'funciona bien, pero' myLong.DoSomething() 'no se compilará. Es un comportamiento bastante esperado para los métodos de extensión, pero difiere de los métodos estáticos regulares. – NOtherDev

4

Personalmente me gusta la legibilidad y las llamadas en cadena (proporciona implícitamente la legibilidad) proporcionadas por los métodos de extensión.

1) Readability: 
    bool empty = String.IsNullOrEmpty (myString) 
    //in comparison to 
    bool empty = myString.IsNullOrEmpty(); 

2) Chain calls: 
    var query = Enumerable.Range(0, 10) 
         .Where(x => x % 2 == 0) 
         .Reverse(); 
    //instead of 
    var query = Enumerable.Reverse(Enumerable.Where(Enumerable.Range(0, 10), x => x % 2 == 0)); 

Con su método de extensión puede ser anulado por miembro de la instancia si accidentalmente lo hace. Personalmente, no me gusta esto. Al menos el compilador debería haber gritado, si está sucediendo en el mismo ensamblado.