¿Hay una manera de forzar a una clase C # para aplicar determinadas funciones estáticas?

StackOverflow https://stackoverflow.com/questions/577749

Pregunta

Estoy desarrollando un conjunto de clases que implementan una interfaz común . Un consumidor de mi biblioteca deberá esperar que cada una de estas clases para implementar un determinado conjunto de funciones estáticas. ¿Hay alguna forma que puedo decorar estas clases para que el compilador detectará el caso en que una de las funciones no se implementa.

Sé que con el tiempo se llamó al construir el código de consumo. Y también sé cómo solucionar este problema utilizando un tipo de clase de fábrica.

Sólo por curiosidad para saber si hay alguna sintaxis / atributos que hay para requerir funciones estáticas en una clase.

Ed Se ha quitado la palabra 'interfaz' para evitar confusiones.

¿Fue útil?

Solución

No, no hay ningún soporte de idioma para esto en C #. Hay dos soluciones que se me ocurre de inmediato:

  • Uso de la reflexión en tiempo de ejecución; los dedos cruzados y la esperanza ...
  • utilizar un singleton / default-instancia / similar a implementar una interfaz que declara los métodos

( actualización )

En realidad, siempre y cuando tenga la unidad de pruebas, la primera opción no es realmente tan malo como se podría pensar que si (como yo) que viene de una estricta fondo "tipos estáticos". El hecho es; que funciona bien en los lenguajes dinámicos. Y, de hecho, esto es exactamente cómo mi código de operadores genéricos funciona - que espera que tiene los operadores estáticas. En tiempo de ejecución, si no lo hace, se ríen de ti en un tono de burla adecuada ... pero no se puede comprobar en tiempo de compilación.

Otros consejos

No. Básicamente parece que usted está después de una especie de "polimorfismo estático". Eso no existe en C #, aunque he sugerido una especie de "noción interfaz estática" que podría ser útil en términos de los genéricos .

Una cosa que podría hacer es escribir una prueba simple unidad para verificar que todos los tipos en un montaje particular, obedezcan a sus reglas. Si otros desarrolladores también estarán implementando la interfaz, se puede poner ese código de prueba en un lugar común, de modo que todo el mundo que implementa la interfaz puede probar fácilmente sus propias asambleas.

Esta es una gran pregunta y una que me he encontrado en mis proyectos.

Algunas personas sostienen que existen interfaces y clases abstractas para el polimorfismo, no para obligar a los tipos de aplicar ciertos métodos. En lo personal, considero polimorfismo de un caso de uso primario, y la ejecución forzada de una secundaria. Hago uso de la técnica de aplicación forzada con bastante frecuencia. Por lo general, aparece en el código marco implementar un patrón de plantilla. La clase base / plantilla encapsula una idea compleja, y subclases proporcionan numerosas variaciones mediante la aplicación de los métodos abstractos. Uno de los beneficios pragmática es que los métodos abstractos de orientación a otros desarrolladores de aplicación de las subclases. Visual Studio incluso tiene la capacidad de código auxiliar los métodos para usted. Esto es especialmente útil cuando un desarrollador de mantenimiento tiene que añadir una nueva subclase meses o años más tarde.

La desventaja es que no hay un apoyo específico para algunos de estos escenarios plantilla en C #. Los métodos estáticos son uno. Otra es constructores; Idealmente, ISerializable debe obligar al desarrollador para implementar el constructor serialización protegida.

El método más sencillo es probablemente (como se sugirió anteriormente) para utilizar una prueba automatizada para comprobar que el método estático se implementa en los tipos deseados. Otra idea viable ya se ha mencionado es la implementación de una regla de análisis estático.

Una tercera opción es utilizar un marco de programación orientada a aspectos tales como PostSharp . PostSharp soporta la validación en tiempo de compilación de aspectos. Se puede escribir código .NET que refleja sobre el conjunto en tiempo de compilación, la generación de avisos y errores arbitrarios. Por lo general, esto se hace para validar que un uso aspecto es apropiado, pero no veo por qué no se podría utilizar para la validación de reglas plantilla también.

Por desgracia, no, no hay nada como esta integrado en el lenguaje.

Si bien no hay soporte de idiomas para esto, se puede utilizar una herramienta de análisis estático para hacerla cumplir. Por ejemplo, podría escribir una regla personalizada para FxCop que detecta una implementación atributo o interfaz en una clase y luego se comprueba la existencia de ciertos métodos estáticos.

El patrón Singleton no ayuda en todos los casos. Mi ejemplo es de un proyecto real de la mía. No se ideó.

Tengo una clase (vamos a llamarlo "Widget") que hereda de una clase en un ORM de terceros. Si una instancia de un objeto de widgets (por lo tanto la creación de una fila en el PP) sólo para asegurarse de que mis métodos estáticos se declaran, estoy haciendo un lío más grande que el que yo estoy tratando de limpiar.

Si creo este objeto extra en el almacén de datos, tengo que ocultarlo de los usuarios, cálculos, etc.

Yo uso de interfaces en C # para asegurarse de que implemento características comunes en un conjunto de clases.

Algunos de los métodos que implementan estas funciones requieren datos de instancia para funcionar. Me codificaré estos métodos como métodos de instancia, y el uso de una interfaz de C # para asegurarse de que existen en la clase.

Algunos de estos métodos no requieren datos de instancia, por lo que son métodos estáticos. Si pudiera declarar interfaces con los métodos estáticos, el compilador podría comprobar si existen o no estos métodos en la clase que dice que implementa la interfaz.

No, no habría ninguna razón para esta función. Las interfaces son básicamente una forma reducida de la herencia múltiple. Le dicen al compilador cómo configurar la tabla de función virtual, de modo que los métodos virtuales no estáticos pueden ser llamados adecuadamente en clases descendientes. Los métodos estáticos no pueden ser virtual, por lo tanto, no hay ningún punto en el uso de interfaces para ellos.

El enfoque que se acerca más a lo que necesita es un producto único, como se sugiere Marc Gravell.

Interfaces, entre otras cosas, permiten proporcionar un cierto nivel de abstracción a sus clases para que pueda utilizar una API determinada independientemente del tipo que lo implementa. Sin embargo, puesto que usted necesita saber el tipo de una clase estática con el fin de usarlo, ¿por qué querrías hacer cumplir esa clase para implementar un conjunto de funciones?

Tal vez usted podría utilizar un atributo personalizado como [ImplementsXXXInterface] y proporcionar un tiempo de ejecución de comprobar para asegurarse de que las clases con este atributo realidad implementan la interfaz que necesita?

Si sólo después de conseguir esos errores de compilación, tenga en cuenta esta configuración:

  1. Definir los métodos en una interfaz.
  2. Para declarar los métodos con abstracta.
  3. Implementar los métodos estáticos públicos, y tienen el método abstracto anula simplemente llamar a los métodos estáticos.

Es un poco de código extra, pero usted sabrá cuando alguien no está implementando un método requerido.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top