una - ¿Las interfaces derivan de System.Object? La especificación de C#dice que sí, Eric dice que no, la realidad dice que no
interfaz asp net (3)
Jon está (como siempre) en el lugar. ¡No es tan fácil como crees!
La especificación es vaga y ligeramente contradictoria. En este caso particular, es probable que sea mejor entrecerrar los ojos un poco y obtener la esencia de lo que la especificación significa transmitir en lugar de analizarla de forma aproximada para obtener definiciones precisas.
El simple hecho del asunto es que "herencia" es un término muy usado en la programación orientada a objetos. (Parece recordar que C ++ tiene seis tipos diferentes de herencia, aunque sería difícil nombrarlos a todos con poca antelación).
Si tuviera mi druthers entonces la especificación de C # claramente llamaría una diferencia entre la herencia y la implementación de la interfaz . La herencia es * una técnica de código compartido para los tipos de clase (y delegado) y struct (y enum) "; su mecanismo es que todos los miembros heredables de un tipo base se convierten en miembros de un tipo derivado . Esto contrasta con la implementación de la interfaz que es un requerimiento de que un tipo de implementación tenga un cierto conjunto de miembros públicos . Esas dos cosas me parecen conceptualmente muy diferentes: una es sobre compartir miembros existentes y la otra es sobre requerir ciertos miembros .
Sin embargo, la especificación no lo hace; confunde los dos bajo la rúbrica de herencia. Dado que estas dos cosas algo diferentes tienen el mismo nombre en la especificación, es difícil razonar con claridad y precisión sobre las diferencias entre ellas.
Personalmente, prefiero pensar que el objeto no es el "tipo base" de ninguna interfaz, y que la interfaz no hereda los miembros del objeto. Que pueda llamarlos en una instancia de una interfaz es más como una cortesía que le extiende el compilador para que no tenga que insertar un molde para objetar allí.
La pregunta es simple y se pregunta en el título.
C # 4.0 La especificación dice: (§4.2.2)
El tipo de clase de objeto es la última clase base de todos los demás tipos. Cada tipo en C # deriva directa o indirectamente del tipo de clase de objeto.
Los tipos de interfaz, que no son clases, no se derivan del objeto.
La realidad dice:
Type t = typeof(ICloneable).BaseType;
Console.WriteLine(t == null);
Cierto
Entonces, ¿las especificaciones son incorrectas o qué? ¿A quién creer?
Los tipos de interfaz no heredan de Object
, pero las ubicaciones de almacenamiento de los tipos de interfaz contienen referencias a objetos de clase que, si no son nulos, tienen la garantía de heredar de System.Object
.
Creo que entender lo que está pasando será más fácil si uno comienza examinando la diferencia entre los tipos de valores y los tipos de clases. Supongamos que tengo una estructura:
public struct SimplePoint {public int x,y;}
y tengo dos métodos
public doSomethingWithPoint(SimplePoint pt) ...
public doSomethingWithObject(Object it) ...
y califique cada método:
SimplePoint myPoint = ...;
doSomethingWithPoint(myPoint);
dosomethingWithObject(myPoint);
La primera llamada no pasa nada que se derive de Object
. En su lugar, pasa los contenidos de todos los campos públicos y privados de SimplePoint
. La segunda llamada necesita algo que se deriva de Object
, por lo que genera una nueva instancia de objeto de montón de tipo SimplePoint
que contiene todos los campos públicos y privados del tipo de valor SimplePoint
y carga todos esos campos con los valores correspondientes de myPoint
. pasa una referencia a ese objeto.
Tenga en cuenta que el tipo SimplePoint
realmente describe dos tipos diferentes de cosas: una colección de campos (es decir, el tipo de valor) y un tipo de objeto de montón. Qué significado es aplicable depende del contexto donde se usa el tipo.
Los tipos de interfaz tienen una arruga similar: cuando se usan como tipos de ubicación de almacenamiento, especifican que la ubicación de almacenamiento contendrá una referencia de objeto. Cuando se usan como restricción genérica, no dicen nada sobre cómo se almacenará el tipo. Por lo tanto, una ubicación de almacenamiento de un tipo de interfaz mantendrá una referencia a un objeto Heap que realmente hereda de System.Object
, pero una variable de un tipo restringido a una interfaz puede contener una referencia o un grupo de campos.
No es una pregunta tan simple como podrías pensar :)
Las interfaces no se derivan del object
pero puede llamar a los miembros del object
sobre ellas. Por lo tanto, puede llamar a ToString()
en una expresión que tenga un tipo de IDisposable
tiempo de IDisposable
, por ejemplo.
Casualmente, sobrevoqué una conversación entre Neal Gafter y Eric en NDC discutiendo exactamente este punto ...
Creo que la sección 4.2.2 de la especificación está muy simplificada, desafortunadamente. Es de esperar que Mads y Eric lo arreglen para una versión futura. Los enviaré por correo para asegurarme de que vean esta pregunta.
También estoy luchando por encontrar algo en la especificación para respaldar el resto de esta respuesta. La sección 3.4.5 de la especificación C # 4 es lo más cerca que puedo encontrar:
Los miembros de una interfaz son los miembros declarados en la interfaz y en todas las interfaces base de la interfaz. Los miembros en el
object
clase no son, estrictamente hablando, miembros de ninguna interfaz (13.2). Sin embargo, los miembros delobject
clase están disponibles a través de la búsqueda de miembros en cualquier tipo de interfaz (7.4).
La conversión de un tipo de interfaz a un object
se trata en la sección 6.1.6:
Las conversiones de referencia implícitas son:
- De cualquier tipo de referencia a
object
ydynamic
.