¿Por qué no puedo heredar clases estáticas?

Tengo varias clases que realmente no necesitan ningún estado. Desde el punto de vista organizativo, me gustaría ponerlos en jerarquía.

Pero parece que no puedo declarar herencia para clases estáticas.

Algo como eso:

public static class Base { } public static class Inherited : Base { } 

no trabajará.

¿Por qué los diseñadores del lenguaje cerraron esa posibilidad?

Cita desde aquí :

Esto es realmente por diseño. Parece que no hay una buena razón para heredar una clase estática. Tiene miembros públicos estáticos a los que siempre se puede acceder a través del nombre de la clase en sí. Las únicas razones que he visto para heredar cosas estáticas han sido malas, como guardar un par de caracteres de tipeo.

Puede haber motivos para considerar mecanismos para incluir miembros estáticos directamente en el scope (y de hecho lo consideraremos después del ciclo de productos de Orcas), pero la herencia estática de clases no es el camino a seguir: es el mecanismo incorrecto para usar, y funciona solo para miembros estáticos que residen en una clase estática.

(Mads Torgersen, Lenguaje C # PM)

Otras opiniones de channel9

La herencia en .NET solo funciona en la base de instancias. Los métodos estáticos se definen en el nivel de tipo, no en el nivel de instancia. Es por eso que la anulación no funciona con métodos / propiedades / eventos estáticos …

Los métodos estáticos solo se guardan una vez en la memoria. No hay una tabla virtual, etc., que se haya creado para ellos.

Si invoca un método de instancia en .NET, siempre le da la instancia actual. Esto está oculto por el tiempo de ejecución de .NET, pero sucede. Cada método de instancia tiene como primer argumento un puntero (referencia) al objeto sobre el que se ejecuta el método. Esto no sucede con los métodos estáticos (como se definen en el nivel de tipo). ¿Cómo debería el comstackdor decidir seleccionar el método para invocar?

(littleguru)

Y como una idea valiosa, littleguru tiene una “solución” parcial para este problema: el patrón de Singleton .

La razón principal por la que no se puede heredar una clase estática es que son abstractas y están selladas (esto también impide que se cree cualquier instancia de ellas).

Así que esto:

 static class Foo { } 

comstack a este IL:

 .class private abstract auto ansi sealed beforefieldinit Foo extends [mscorlib]System.Object { } 

Piénselo de esta manera: accede a los miembros estáticos a través del nombre del tipo, como este:

 MyStaticType.MyStaticMember(); 

Si heredases de esa clase, tendrías que acceder a ella a través del nuevo nombre de tipo:

 MyNewType.MyStaticMember(); 

Por lo tanto, el nuevo elemento no guarda relación con el original cuando se usa en el código. No habría forma de aprovechar cualquier relación de herencia para cosas como el polymorphism.

Tal vez estás pensando que solo quieres extender algunos de los elementos en la clase original. En ese caso, no hay nada que le impida usar simplemente un miembro del original en un tipo completamente nuevo.

Quizás desee agregar métodos a un tipo estático existente. Ya puedes hacerlo a través de los métodos de extensión.

Quizás desee poder pasar un Type estático a una función en tiempo de ejecución y llamar a un método de ese tipo, sin saber exactamente qué hace el método. En ese caso, puede usar una interfaz.

Entonces, al final no ganas nada heredando clases estáticas.

Lo que desea lograr mediante el uso de la jerarquía de clases se puede lograr simplemente a través del espacio de nombres. Por lo tanto, los lenguajes que admitan espacios de nombre (como C #) no tendrán uso de implementar jerarquía de clase de clases estáticas. Como no puede crear instancias de ninguna de las clases, todo lo que necesita es una organización jerárquica de las definiciones de clase que puede obtener mediante el uso de espacios de nombres

Puede usar composición en su lugar … esto le permitirá acceder a objetos de clase desde el tipo estático. Pero aún no se pueden implementar interfaces o clases abstractas

Aunque puede acceder a miembros estáticos “heredados” a través del nombre de clases heredado, los miembros estáticos realmente no se heredan. Esto es, en parte, por qué no pueden ser virtuales o abstractos y no pueden anularse. En su ejemplo, si declaró un Método Base (), el comstackdor correlacionará una llamada a Método_herida () de nuevo a Método_base_ () de todos modos. También puede llamar a Base.Method () explícitamente. Puede escribir una pequeña prueba y ver el resultado con Reflector.

Entonces … si no puede heredar miembros estáticos, y si las clases estáticas solo pueden contener miembros estáticos, ¿de qué serviría heredar una clase estática?

Hmmm … ¿sería muy diferente si solo tuvieras clases no estáticas con métodos estáticos …?

Una solución alternativa que puede hacer es no utilizar clases estáticas sino ocultar el constructor para que los miembros estáticos de las clases sean los únicos accesibles fuera de la clase. El resultado es esencialmente una clase “estática” heredable:

 public class TestClass { protected TestClass() { } public static T Add(T x, T y) { return (dynamic)x + (dynamic)y; } } public class TestClass : TestClass { // Inherited classes will also need to have protected constructors to prevent people from creating instances of them. protected TestClass() { } } TestClass.Add(3.0, 4.0) TestClass.Add(3, 4) // Creating a class instance is not allowed because the constructors are inaccessible. // new TestClass(); // new TestClass(); 

Desafortunadamente, debido a la limitación del lenguaje “por diseño” no podemos hacer:

 public static class TestClass { public static T Add(T x, T y) { return (dynamic)x + (dynamic)y; } } public static class TestClass : TestClass { } 

Puedes hacer algo que se parezca a la herencia estática.

Aquí está el truco:

 public abstract class StaticBase where TSuccessor : StaticBase, new() { protected static readonly TSuccessor Instance = new TSuccessor(); } 

Entonces puedes hacer esto:

 public class Base : StaticBase { public Base() { } public void MethodA() { } } public class Inherited : Base { private Inherited() { } public new static void MethodA() { Instance.MethodA(); } } 

La clase Inherited no es estática en sí misma, pero no permitimos crearla. En realidad, ha heredado el constructor estático que construye Base y todas las propiedades y métodos de Base disponibles como estáticos. Ahora, lo único que queda por hacer es envoltorios estáticos para cada método y propiedad que necesita exponer a su contexto estático.

Hay inconvenientes como la necesidad de creación manual de métodos de envoltura estática y new palabra clave. Pero este enfoque ayuda a respaldar algo que es realmente similar a la herencia estática.

PD Lo usamos para crear consultas comstackdas, y esto en realidad puede reemplazarse con ConcurrentDictionary, pero un campo de solo lectura estático con seguridad de subprocesos fue lo suficientemente bueno.

Las clases estáticas y los miembros de la clase se utilizan para crear datos y funciones a los que se puede acceder sin crear una instancia de la clase. Los miembros de clase estática se pueden utilizar para separar datos y comportamientos que son independientes de cualquier identidad de objeto: los datos y las funciones no cambian independientemente de lo que le ocurra al objeto. Las clases estáticas se pueden usar cuando no hay datos o comportamientos en la clase que dependen de la identidad del objeto.

Una clase puede declararse estática, lo que indica que solo contiene miembros estáticos. No es posible usar la nueva palabra clave para crear instancias de una clase estática. El .NET Framework Common Language Runtime (CLR) carga automáticamente las clases estáticas cuando se carga el progtwig o el espacio de nombres que contiene la clase.

Use una clase estática para contener métodos que no están asociados con un objeto en particular. Por ejemplo, es un requisito común crear un conjunto de métodos que no actúen sobre datos de instancia y que no estén asociados a un objeto específico en su código. Podría usar una clase estática para contener esos métodos.

Las siguientes son las características principales de una clase estática:

  1. Solo contienen miembros estáticos.

  2. No pueden ser instanciados.

  3. Ellos están sellados.

  4. No pueden contener constructores de instancias (Guía de progtwigción C #).

Por lo tanto, crear una clase estática es básicamente lo mismo que crear una clase que contenga solo miembros estáticos y un constructor privado. Un constructor privado evita que la clase sea instanciada.

La ventaja de utilizar una clase estática es que el comstackdor puede verificar para asegurarse de que no se agreguen accidentalmente miembros de la instancia. El comstackdor garantizará que no se pueden crear instancias de esta clase.

Las clases estáticas están selladas y, por lo tanto, no se pueden heredar. No pueden heredar de ninguna clase excepto Object. Las clases estáticas no pueden contener un constructor de instancia; sin embargo, pueden tener un constructor estático. Para obtener más información, vea Constructores estáticos (Guía de progtwigción de C #).

Cuando creamos una clase estática que contiene solo los miembros estáticos y un constructor privado. La única razón es que el constructor estático impide que la clase sea instanciada, por lo que no podemos heredar una clase estática. La única forma de acceder al miembro del clase estática utilizando el nombre de la clase en sí. Intentar heredar una clase estática no es una buena idea.