¿Deberían ser estáticos los métodos de C # que pueden ser estáticos?
Estuvimos discutiendo esto hoy y estoy un poco indeciso. Imagina que tienes un método largo del que refactorizas algunas líneas. El nuevo método probablemente toma algunas variables locales del método principal y devuelve un valor. Esto significa que podría ser estático.
La pregunta es: ¿ debería ser estático? No es estático por diseño o elección, simplemente por su naturaleza, ya que no hace referencia a ningún valor de instancia.
Respuestas:
Depende. Realmente hay 2 tipos de métodos estáticos:
En una base de código de tamaño pequeño a mediano, realmente puede tratar los dos métodos de manera intercambiable.
Si tiene un método que está en la primera categoría (puede ser estático) y necesita cambiarlo para acceder al estado de la clase, es relativamente sencillo averiguar si es posible convertir el método estático en un método de instancia.
Sin embargo, en una base de código grande, la gran cantidad de sitios de llamadas puede hacer que la búsqueda para ver si es posible convertir un método estático en uno no estático sea demasiado costosa. Muchas veces la gente verá la cantidad de llamadas y dirá "ok ... mejor no cambiar este método, sino crear uno nuevo que haga lo que necesito".
Eso puede resultar en:
Ambas cosas son malas.
Entonces, mi consejo sería que si tiene una base de código de más de 200K LOC, solo haría que los métodos sean estáticos si son métodos que deben ser estáticos.
La refactorización de no estático a estático es relativamente fácil (solo agregue una palabra clave), por lo que si desea convertir un can-be-static en uno estático real más adelante (cuando necesite su funcionalidad fuera de una instancia), entonces puede hacerlo. Sin embargo, la refactorización inversa, convertir un método can-be-static en un método de instancia, es MUCHO más caro.
Con bases de código grandes, es mejor equivocarse por el lado de la facilidad de extensión, en lugar del lado de la pureza idealológica.
Por lo tanto, para proyectos grandes, no hagas las cosas estáticas a menos que lo necesites. Para proyectos pequeños, haga lo que más le guste.
fuente
Yo no lo convierten en un público miembro estático de la clase . La razón es que hacerlo público estático es decir algo sobre el tipo de clase: no solo "este tipo sabe cómo realizar este comportamiento", sino también "es responsabilidad de este tipo realizar este comportamiento". Y lo más probable es que el comportamiento ya no tenga una relación real con el tipo más grande.
Sin embargo, eso no significa que no lo haría estático en absoluto. Pregúntese esto: ¿podría el nuevo método lógicamente pertenecer a otra parte? Si puede responder "sí" a eso, probablemente quiera hacerlo estático (y moverlo también). Incluso si eso no es cierto, aún podría hacerlo estático. Simplemente no lo marques
public
.Por conveniencia, al menos podría marcarlo
internal
. Por lo general, esto evita la necesidad de mover el método si no tiene acceso fácil a un tipo más apropiado, pero aún lo deja accesible donde sea necesario de una manera que no se mostrará como parte de la interfaz pública para los usuarios de su clase. .fuente
No necesariamente.
Mover los métodos públicos de estáticos a no estáticos es un cambio radical y requeriría cambios para todas las personas que llaman o consumidores. Si un método parece un método de instancia, pero resulta que no usa ningún miembro de instancia, sugeriría convertirlo en un método de instancia como una medida de prueba de futuro.
fuente
Si. La razón por la que "puede ser estático" es que no opera en el estado del objeto sobre el que se llama. Por lo tanto, no es un método de instancia, sino un método de clase. Si puede hacer lo que debe hacer sin tener que acceder a los datos de la instancia, entonces debería ser estático.
fuente
Sí, debería. Hay varias métricas de acoplamiento que miden cómo su clase depende de otras cosas, como otras clases, métodos, etc. Hacer que los métodos sean estáticos es una forma de mantener bajo el grado de acoplamiento, ya que puede estar seguro de que un método estático no hace referencia a ninguno. miembros.
fuente
Creo que lo haría un poco más legible si lo marcara como estático ... Entonces alguien que venga sabría que no hace referencia a ninguna variable de instancia sin tener que leer la función completa ...
fuente
Personalmente, soy un gran fanático de la apatridia. ¿Tu método necesita acceso al estado de la clase? Si la respuesta es no (y probablemente sea no, de lo contrario no consideraría convertirlo en un método estático), entonces sí, adelante.
No tener acceso al estado es menos dolor de cabeza. Así como es una buena idea ocultar los miembros privados que no son necesarios para otras clases, es una buena idea ocultar el estado a los miembros que no lo necesitan. El acceso reducido puede significar menos errores. Además, facilita el enhebrado, ya que es mucho más fácil mantener los miembros estáticos seguros para los subprocesos. También hay una consideración de rendimiento, ya que el tiempo de ejecución no necesita pasar una referencia a esto como un parámetro para los métodos estáticos.
Por supuesto, la desventaja es que si alguna vez descubre que su método previamente estático tendrá que acceder al estado por alguna razón, entonces debe cambiarlo. Ahora entiendo que esto puede ser un problema para las API públicas, por lo que si se trata de un método público en una clase pública, tal vez debería pensar un poco en las implicaciones de esto. Aún así, nunca me he enfrentado a una situación en el mundo real en la que esto realmente haya causado un problema, pero tal vez tenga suerte.
Así que sí, adelante, por supuesto.
fuente
Los métodos estáticos son más rápidos que los no estáticos, así que sí, deberían ser estáticos si pueden y no hay ninguna razón especial para dejarlos no estáticos .
fuente
Me sorprende que, de hecho, tan pocos mencionen la encapsulación aquí. Un método de instancia tendrá acceso automáticamente a todos los campos, propiedades y métodos privados (de instancia). Además de todos los protegidos heredados de las clases base.
Cuando escribes código debes hacerlo de modo que expongas lo menos posible y también para que tengas acceso a lo menos posible.
Entonces, sí, podría ser importante hacer que su código sea rápido, lo que sucedería si está haciendo que sus métodos sean estáticos, pero generalmente es más importante hacer que su código sea lo más incapaz posible de crear errores también. Una forma de lograrlo es que su código tenga acceso a la menor cantidad posible de "cosas privadas".
Esto puede parecer irrelevante a primera vista, ya que el OP está hablando obviamente de refactorización que no puede salir mal en este escenario y crear nuevos errores, sin embargo, este código refactorizado debe mantenerse en el futuro y modificarse, lo que hace que su código tenga un mayor "ataque". Surface "con respecto a nuevos errores si tiene acceso a miembros de instancias privadas. Entonces, en general, creo que la conclusión aquí es que "sí, la mayoría de sus métodos deben ser estáticos" a menos que haya otras razones para no tenerlos estáticos. Y esto simplemente porque es "un mejor uso de la encapsulación y el ocultamiento de datos y crea un código 'más seguro'" ...
fuente
Hacer algo estático solo porque puedes no es una buena idea. Los métodos estáticos deben ser estáticos debido a su diseño, no por casualidad.
Como dijo Michael, cambiar esto más tarde romperá el código que lo está usando.
Dicho esto, parece que está creando una función de utilidad privada para la clase que, de hecho, es estática por diseño.
fuente
Si pudo refactorizar algunas líneas y el método resultante podría ser estático, probablemente sea una indicación de que las líneas que sacó de ese método no pertenecen en absoluto a la clase contenedora, y debería considerar moverlas a su propia clase.
fuente
Personalmente, no tendría más remedio que hacerlo estático. Resharper emite una advertencia en este caso y nuestro PM tiene una regla "No hay advertencias del Resharper".
fuente
Depende, pero generalmente no hago que esos métodos sean estáticos. El código siempre cambia y quizás algún día quiera hacer que esa función sea virtual y anularla en una subclase. O quizás algún día tendrá que hacer referencia a variables de instancia. Será más difícil realizar esos cambios si es necesario cambiar todos los sitios de llamadas.
fuente
Sugiero que la mejor manera de pensarlo es la siguiente: si necesita un método de clase que deba llamarse cuando no se crean instancias de la clase, o mantiene algún tipo de estado global, entonces estático es una buena idea. Pero, en general, sugiero que prefiera que los miembros no sean estáticos.
fuente
Deberías pensar en tus métodos y clases:
Si los dos últimos son 'sí', entonces su método / clase probablemente debería ser estático.
El ejemplo más utilizado es probablemente el
Math
clase. Todos los principales lenguajes OO lo tienen y todos los métodos son estáticos. Porque necesitas poder usarlos en cualquier lugar, en cualquier momento, sin crear una instancia.Otro buen ejemplo es el
Reverse()
método en C #.Este es un método estático en el
Array
clase. Invierte el orden de su matriz.Código:
Ni siquiera devuelve nada, su matriz se invierte, porque todas las matrices son instancias de la clase Array.
fuente
Siempre que haga que el nuevo método sea privado y estático, no será un cambio importante. De hecho, FxCop incluye esta guía como una de sus reglas ( http://msdn.microsoft.com/en-us/library/ms245046(VS.80).aspx ), con la siguiente información:
Dicho esto, el primer comentario de David Kean resume de manera más sucinta las preocupaciones diciendo que en realidad se trata más de ser correcto que de mejorar el rendimiento:
fuente
Definitivamente convertiría todo lo que pueda en estático por una razón diferente:
Las funciones estáticas, cuando están JIT, se llaman sin un parámetro "this". Eso significa, por ejemplo, que una función no estática de 3 parámetros (método de miembro) se inserta con 4 parámetros en la pila.
La misma función compilada como función estática se llamaría con 3 parámetros. Esto puede liberar registros para el JIT y ahorrar espacio en la pila ...
fuente
Estoy en el campo de "solo hacer estáticos los métodos privados". Hacer un método público puede introducir un acoplamiento que no desea y puede disminuir la capacidad de prueba: no puede bloquear un método estático público.
Si desea realizar una prueba unitaria de un método que usa un método estático público, también terminará probando el método estático, que podría no ser lo que desea.
fuente
Los métodos inherentemente estáticos que por alguna razón se hacen no estáticos son simplemente molestos. Esto es:
Llamo a mi banco y pregunto por mi saldo.
Piden mi número de cuenta.
Lo suficientemente justo. Método de instancia.
Llamo a mi banco y les pido su dirección postal.
Piden mi número de cuenta.
WTF? Fallar: debería haber sido un método estático.
fuente
Lo miro generalmente desde una perspectiva funcional de funciones puras. ¿Necesita ser un método de instancia? De lo contrario, puede beneficiarse de obligar al usuario a pasar las variables y no alterar el estado de la instancia actual. (Bueno, aún podría alterar el estado, pero el punto es, por diseño, no hacerlo). Generalmente diseño métodos de instancia como miembros públicos y hago todo lo posible para que los miembros privados sean estáticos. Si es necesario (puede extraerlos más fácilmente en otras clases más adelante.
fuente
En esos casos, tiendo a mover el método a una biblioteca estática o utils, así que no estoy mezclando el concepto de "objeto" con el concepto de "clase".
fuente