programacion - metodos y funciones en c#
¿Por qué no se admiten los métodos de extensión de clases estáticos de C#? (6)
Sé por esta pregunta que los métodos de extensión solo pueden operar en instancias de clase, no en la clase estática en sí misma. Esto significa que no puedo extender clases estáticas útiles como Convert
y Math
.
Lo que quiero saber es, ¿por qué es este el caso? Desde el enlace de arriba, hay algunas sugerencias sobre cómo el equipo de C # podría haber implementado este tipo de funcionalidad. ¿Hay alguna razón filosófica por la cual no es compatible?
Por ejemplo, aquí hay un rationale detrás de por qué no hay una extensión incorporada de LINQ ForEach<T>
para IEnumerable<T>
.
el equipo de C # podría haber implementado este tipo de funcionalidad. ¿Hay alguna razón filosófica por la cual no es compatible?
No hay razón técnica ni razón filosófica. Sin embargo, como a menudo señalo, no tengo que proporcionar una justificación para no hacer una función. Las características no son baratas; son extremadamente caros y no solo deben justificar su propio costo, deben justificar el costo de oportunidad de no hacer las otras cien funciones que podríamos haber hecho con ese presupuesto. Debemos justificar el costo de las funciones para nuestros grupos de interés, pero no tenemos que justificar el ahorro de tiempo y esfuerzo al no implementar las funciones que no cumplen con nuestra barra.
En particular, la característica propuesta no hace nada para LINQ; Se agregaron métodos de extensión para hacer que LINQ funcione. Cualquier cosa que no hiciera funcionar LINQ era muy difícil de conseguir en C # 3.0; trabajamos mucho en el cronograma y no tuvimos mucho tiempo para hacerlo (me sorprendió que las propiedades automáticas lo incluyeran). Cortar una característica innecesaria antes de diseñarla ahorró mucho tiempo y esfuerzo que se gastó en otra cosas que hacen que LINQ funcione.
En resumen: la función sugerida nunca se ha reunido con nuestro colega para obtener un beneficio neto sobre el costo, y siempre hemos tenido características más importantes para dedicar nuestro tiempo y esfuerzo limitados.
Bueno, no solo no está implementado, sino que causará confusión sobre el lugar al que pertenece el método. Las extensiones estáticas se introdujeron porque Linux entró en la versión posterior y solo para admitir linq de manera fácil de codificar, las extensiones estáticas son útiles.
Las extensiones estáticas son útiles solo para hacer que el código sea más legible. No tiene importancia en tiempo de ejecución o tiempo de compilación.
Creo que la respuesta a su pregunta es because it doesn''t make any sense to extend with static methods
. La razón principal detrás de la introducción de los Extension methods
no es extending
clase que no es de su propiedad. La razón principal es que permitirá reducir los métodos de anidación en ejemplos como estos:
Enumerable.Select(Enumerable.Where(arr, i => i & 1 == 0), i => i*i); // not the best thing I ever read
arr.Where(i => i&1 == 0).Select(i => i*i); // wow, I see! These are squares for odd numbers
Es por eso que no hay tal punto para tener métodos de extension
para clases estáticas.
Después de leer las respuestas, así como algunas preguntas relacionadas, he reunido mi comprensión del problema aquí.
Cómo funcionan los métodos de extensión
En primer lugar, es importante darse cuenta de que las extensiones son solo azúcar sintáctica para métodos estáticos.
// Say you have an extension method that looks like this:
class Extensions
{
public static void Extend(this SomeClass foo) {}
}
// Here''s how you call it
SomeClass myClass;
myClass.Extend();
// The compiler converts it to this:
Extensions.Extend(myClass);
El método en realidad no se convierte en parte de la clase. Es por eso que no puede acceder a miembros privados desde un método de extensión. Los métodos de extensión solo modifican la sintaxis de C # y no violan el concepto de accesibilidad OOP. De hecho, si escribe un método de extensión y un método estático normal que hacen lo mismo, entonces descompile el MSIL, son exactamente lo mismo .
Por qué existen los métodos de extensión
Entonces, si no agregan funcionalidad real, ¿por qué tienen métodos de extensión? La respuesta es LINQ:
// LINQ makes this easy to read
array.Where(i => i&1 == 0).Select(i => i*i);
// Without extension methods, we would have to do it like this
Enumerable.Select(Enumerable.Where(array, i => i&1 == 0), i => i*i);
En cierto modo, todo LINQ es solo azúcar sintáctico, ya que todo lo que puede hacer se puede escribir de una manera torpe, no LINQy. Obviamente, el equipo C # consideró que la legibilidad obtenida por LINQ valió la pena, pero plantea la pregunta, "¿por qué se detuvieron allí?"
¿Por qué no otros tipos de extensión?
Eric Lippert, uno de los desarrolladores de compiladores de C #, describió en una publicación de blog que una gran parte de C # 3 creaba todas las construcciones necesarias para LINQ: "locales implícitamente tipados, tipos anónimos, expresiones lambda, métodos de extensión, inicializadores de objetos y colecciones , comprensión de consultas, árboles de expresión, [y] inferencia mejorada del tipo de método ". Debido a que el equipo C # era el equipo más limitado en recursos para la versión .NET 2008, no se incluyeron tipos adicionales de extensiones que no eran estrictamente necesarias para LINQ.
El equipo sí consideró la implementación de propiedades de extensión en C # 4, y en realidad escribió un prototipo funcional, pero se eliminó cuando descubrieron que no habilitaría al equipo de WPF tal como se implementó (que fue uno de los factores motivadores de la función). Eric Lipper luego dijo que ellos consideraban métodos de extensión para clases estáticas, pero no podían justificar los beneficios del mundo real contra los costos de implementación, prueba y mantenimiento.
Una solución
Es posible escribir un método de extensión que se acerque:
public static TResult DoSomething<TType, TResult>(this TType @class)
{
// access static methods with System.Reflection
return default(TResult);
}
// This works, but poorly
typeof(Math).DoSomething();
typeof(Convert).DoSomething();
Pero es bastante feo. Requiere reflexión y no admite ningún tipo de tipeo inteligente, ya que cualquier Type
puede llamarlo y es probable que no sea la funcionalidad prevista.
Las extensiones estáticas son posibles en F #:
type Platform =
| Win32
| X64
override this.ToString() =
match FSharpValue.GetUnionFields(this, typeof<Platform>) with
| case, _ -> case.Name.Replace(''X'', ''x'')
type Environment with
static member Platform =
if System.IntPtr.Size = 8 then Platform.X64 else Platform.Win32
Los métodos de extensión operan en objetos, no en clases. Si quieres un método de extensión para operar en una clase, supongo que podrías hacer esto:
public static T DoSomething<T>(this T @class)
where T:Type
{
// access static methods via reflection...
return @class;
}