c# - ¿Por qué las clases estáticas se consideran "clases" y "tipos de referencia"?
static clr (10)
He estado reflexionando sobre el sistema de tipo C # y CIL hoy y comencé a preguntarme por qué las clases estáticas se consideran clases. Hay muchas formas en que no son realmente las clases:
- Una clase "normal" puede contener miembros no estáticos, una clase estática no puede. En este sentido, una clase es más similar a una estructura que a una clase estática, y sin embargo las estructuras tienen un nombre diferente.
- Puede tener una referencia a una instancia de una clase "normal", pero no a una clase estática (a pesar de que se considera un "tipo de referencia"). En este sentido, una clase es más similar a una interfaz que a una clase estática, y sin embargo las interfaces tienen un nombre diferente.
- El nombre de una clase estática nunca se puede usar en ningún lugar donde un nombre de tipo encajaría normalmente: no se puede declarar una variable de este tipo, no se puede usar como tipo base y no se puede usar como un parámetro de tipo genérico. En este sentido, las clases estáticas son algo más como espacios de nombres .
- Una clase "normal" puede implementar interfaces. Una vez más, eso hace que las clases sean más similares a las estructuras que a las clases estáticas.
- Una clase "normal" puede heredar de otra clase.
También es extraño que se considere que las clases estáticas derivan de System.Object . Aunque esto les permite "heredar" los métodos estáticos Equals y ReferenceEquals , el propósito de esa herencia es cuestionable, ya que de todos modos usted llamaría a esos métodos en el objeto . C # incluso le permite especificar esa herencia inútil explícitamente en clases estáticas, pero no en interfaces o estructuras, donde la derivación implícita del objeto y System.ValueType , respectivamente, tiene un propósito.
Con respecto al argumento del subconjunto de características: las clases estáticas tienen un subconjunto de las características de las clases, pero también tienen un subconjunto de las características de las estructuras. Todas las cosas que hacen que una clase sea distinta de los otros tipos de tipos, no parecen aplicarse a las clases estáticas.
Con respecto al argumento typeof : Convertir una clase estática en un tipo de tipo nuevo y diferente no impide que se use en typeof .
Dada la gran rareza de las clases estáticas y la escasez de similitudes entre ellas y las clases "normales", ¿no deberían haberse convertido en un tipo separado de tipo en lugar de un tipo especial de clase?
¿Qué pasa con los constructores estáticos? Creo que este es otro aspecto importante a considerar en su comparación. Las clases y las estructuras los admiten, pero las interfaces y los espacios de nombres no.
La construcción implica instanciación. Si bien la implementación en realidad no puede crear una "instancia" de una clase estática, puede ver las clases estáticas como una instancia de singleton de una clase, a la que solo puede haber una referencia (el propio nombre de tipo). Si pudiera heredar clases estáticas, rompería la noción de singleton. Si pudiera declarar variables del tipo, podría esperar que el recolector de basura las limpie cuando ya no estén referenciadas.
¿Por qué son clases en lugar de estructuras? Cuando pienso en estructuras (tipos de valor), pienso en valores en la pila. Su existencia es (típicamente) muy corta y se copian con frecuencia. Esto rompe de nuevo la noción de referencia única de singleton anterior.
Aunque los tipos de clase, los tipos de valor y las interfaces se comportan en muchos aspectos como si estuvieran en tres tipos diferentes de cosas, en realidad se describen usando el mismo tipo de objeto Type
; la paternidad de un tipo determina qué tipo de cosa es. En particular, todos los tipos en .NET son tipos de clase excepto por lo siguiente:
Tipos diferentes a
System.Object
que heredan denull
; esas son interfacesTipos distintos de
System.ValueType
oSystem.Enum
que heredan deSystem.ValueType
oSystem.Enum
; esos son tipos de valor.Algunos tipos, como punteros y referencias, que pueden identificarse con los objetos
Type
(necesarios para elementos como los tipos de parámetros), pero que no tienen miembros de la misma forma que otros tipos.
Cada tipo que tiene miembros y cuya filiación no cumple ninguno de los criterios anteriores, se considera una clase. Las clases estáticas no son en realidad clases debido a la calidad particular que tienen, sino porque no tienen ninguna cualidad que las convierta en otro tipo de cosas con nombre, y llamarlas "clases estáticas" parece más fácil que inventar otras Término para describirlos.
Buen punto, probablemente se deba a razones históricas, es decir, no querían inventar algo nuevo ya que las clases estáticas ya existían.
C ++, Pascal (Delphi) y Java tienen clases estáticas, y en eso se basa C #.
Claro, podrían haber sido convertidos en un tipo separado de cosas.
Pero eso habría requerido un trabajo adicional en el CLR, el BCL y en todos los equipos de idiomas, y yo habría dejado otras cosas más importantes por hacer.
Desde un punto de vista puramente estético, podría estar de acuerdo contigo.
En mi opinión, las clases estáticas se consideran así porque pueden incrustar campos privados, propiedades públicas y métodos, aunque son estáticos, y tienen una ubicación de dirección fija donde cada llamada al método o propiedad de singleton tendrá su referencia.
Una estructura es más probable que sea un tipo de valor como cuando escribes:
var struct1 = new Struct1();
var struct2 = struct1;
cada una de las propiedades se habrá copiado en una nueva ubicación de memoria. Además, con una estructura, podrá cambiar el valor de struct2.Property1 sin que se haya cambiado dentro de struct1.Property1.
Por oposición, las clases son en mi comprensión tipos de referencia, como cuando escribes:
var class1 = new Class1();
var class2 = class1;
Aquí, la referencia se copia. Esto significa que cuando cambia class2.Property1, esta misma propiedad también cambiará en class1.Property1. Esto se debe a que ambas clases apuntan a la misma dirección de memoria.
En cuanto a las clases estáticas, se consideran como tipos de referencia cuando, al cambiar un valor StaticClass.Property dentro de un método, este cambio se completará en todos los lugares donde haga referencia a esta clase. Solo tiene una dirección de memoria y no se puede copiar, de modo que cuando ocurra otro método o llamada de propiedad, este nuevo valor prevalecerá sobre el anterior. Las clases estáticas están destinadas a compartirse en una aplicación completa, por lo que solo existe una referencia para ella dentro de su aplicación. Por lo tanto haciéndolos comportarse como una clase.
Una clase estática, aunque el patrón de singleton no está, supongo, se recomienda, excepto para un propósito absoluto, podría representar un objeto de la vida real como una clase o una instancia de una clase. Sin embargo, dado que los objetos únicos en el mundo parecen ser lo suficientemente raros, realmente no los necesitamos para representar un objeto práctico, sino simplemente algunos lógicos, como herramientas, etc., o algún otro método costoso. Instalar objetos.
EDITAR De hecho, una clase estática es tan similar a una clase que en Visual Basic, no hay una clase estática, sino solo una clase con miembros estáticos (Compartidos en Visual Basic). El único punto a considerar es hacer esta clase NotInheritable (sellada en C #). Entonces, C # proporciona una funcionalidad más implícita al permitir declarar una clase estática, en lugar de sellarla, con un constructor predeterminado vacío, etc. Esto es una especie de atajo, o azúcar sintáctica, como nos gusta decir.
En conclusión, no creo que haya ningún beneficio o beneficio si se cuenta con una nueva palabra clave.
Es una clase en lo que concierne al CLR. Es simplemente el azúcar sintáctico en el compilador de C #, básicamente.
No creo que haya ningún beneficio al agregar un nombre diferente aquí, se comportan principalmente como clases que solo tienen métodos estáticos y no se pueden construir, que generalmente es el tipo de clase que se convirtió en una clase estática cuando pasamos de C # 1 a C # 2.
Tenga en cuenta que si desea crear un nuevo nombre para él, eso probablemente significa una nueva palabra clave también ...
Las clases estáticas y las clases (y estructuras) "normales" son contenedores para el código ejecutable (campos miembros, propiedades, métodos) y declaran un Type
. Si tuvieran una palabra diferente para esto, entonces preguntaríamos lo contrario ("si son tan similares, ¿por qué no usaste la clase de kayword?"). Sugeriría "CLR a través de C #", donde está bien explicado cómo ocurre la resolución de tipos, la llamada a métodos, etc. Funciona de la misma manera para "ambas" clases, solo los miembros de la instancia tienen un parámetro adicional pasado para el objeto de la instancia.
Las clases no son como espacios de nombres porque son solo para nombrar y hacer referencia. No afectan la funcionalidad de la clase.
Las clases también son diferentes de las interfaces, porque las interfaces son simplemente herramientas de verificación en tiempo de compilación y no tienen funcionalidad propia.
No sé si esto califica como una respuesta, pero señalaría que las "clases estáticas" son más un concepto de lenguaje y menos un concepto de CLR. Desde el punto de vista del CLR, son solo clases, como cualquier otra. Depende del idioma hacer cumplir todas las reglas que describió.
Como tal, una de las ventajas de la implementación actual es que no agrega mayor complejidad al CLR, que todos los lenguajes de orientación CLR deberían comprender y modelar.
Sí, son muy raros. Tienen algún tipo de comportamiento de clase, como poder tener variables de miembro (estáticas) y restringir el acceso a los miembros usando público / privado.
Casi escribí "público / protegido / privado" allí, pero obviamente protegido no tiene sentido, porque no hay herencia de método de clases estáticas. Creo que la razón principal de esto es que, como no hay instancias, no se puede tener polimorfismo, pero esa no es realmente la única razón para heredar. El polimorfismo es genial, pero a veces solo quieres tomar prestada la mayor parte de la funcionalidad de la clase base y agregar algunas cosas por tu cuenta. Debido a esto, a veces verá que las clases estáticas cambian para usar patrones singleton, solo para que pueda aprovechar algunas de las funciones del conjunto básico de clases. En mi opinión, este es un intento de hacky para cerrar esa brecha, y se vuelve confuso e introduce una gran complejidad antinatural. La otra opción es la agregación, donde los métodos de clase secundaria solo pasan las llamadas a los métodos de clase primaria, pero esto requiere una gran cantidad de código para unirlo todo y tampoco es una solución perfecta.
En estos días, las clases estáticas generalmente se usan solo como un reemplazo de los métodos globales, es decir, métodos que solo proporcionan funcionalidad sin estar vinculados a una instancia de nada. Los puristas de OO odian cualquier concepto de una cosa libre / global flotando alrededor, pero tampoco desea tener que tener una instancia y un objeto innecesarios flotando alrededor si solo necesita funcionalidad, por lo que una "clase" estática proporciona un punto medio compromiso con el que ambas partes pueden estar de acuerdo.
Así que sí, las clases estáticas son extrañas. Idealmente, sería bueno si pudieran dividirse en su propio concepto que proporcionara la flexibilidad y la facilidad de uso liviana que obtiene de los métodos que no necesitan estar vinculados a una instancia (que ahora tenemos con clases estáticas). ), y también agrupa esos métodos en contenedores (que también tenemos ahora), pero también proporciona la capacidad de definir una entidad base de la que heredará métodos (esta es la parte que falta ahora). Además, sería genial que fuera un concepto separado de las clases, por las razones exactas que plantea, simplemente se vuelve confuso porque la gente, naturalmente, espera que las clases sean instancias con propiedades y métodos que se pueden crear y destruir.
Su pregunta es "¿por qué tengo que escribir las palabras static class X
lugar de foobar X
". La respuesta es que los programadores ya asocian la palabra "clase" con "un paquete de funciones encapsuladas y empaquetadas que alguien escribió para mí". Lo que, casualmente, encaja perfectamente con la definición de clases estáticas.
Podrían haber usado espacios de nombres en su lugar, sí. Eso es lo que pasa en C ++. Pero el término ''clase estática'' tiene una ventaja aquí: implica un grupo más pequeño y mucho más estrechamente unido de funcionalidad. Por ejemplo, puede tener un espacio de nombres llamado Qt o boost :: asio pero una clase estática llamada StringUtils o KWindowSystem (para tomar prestada una de KDE).