c# - que - no se puede crear una instancia de una interfaz
Interfaz interna de C#con implementación interna (5)
Está bien tener un modificador interno en una declaración de interfaz, pero NO PUEDE tener NINGÚN modificador DENTRO de la interfaz, en otras palabras, no puede haber ningún modificador para los miembros de la interfaz. ¡Es así de simple!
Ejemplo:
internal interface IA
{
void X(); //OK. It will work
}
internal class CA : IA
{
**internal** void X() // internal modifier is NOT allowed on any Interface members. It doesn''t compile. If it works in your project it''s because either you DON''T have the void X() method in the Interface or your are inheriting from a wrong interface maybe accidentally
{
...
}
}
Una declaración de interfaz puede declarar cero o más miembros. Los miembros de una interfaz deben ser métodos, propiedades, eventos o indexadores. Una interfaz no puede contener constantes, campos, operadores, constructores de instancias, destructores o tipos, ni una interfaz puede contener miembros estáticos de ningún tipo. Todos los miembros de la interfaz implícitamente tienen acceso público. Es un error de tiempo de compilación para las declaraciones de los miembros de la interfaz para incluir cualquier modificador. En particular, los miembros de la interfaz no se pueden declarar con los modificadores abstractos, públicos, protegidos, internos, privados, virtuales, sobrescritos o estáticos.
Referencia: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/interfaces
Me he topado con algo que realmente no entiendo.
Tengo un proyecto, donde tengo una interfaz que es interna. La clase que implementa esa interfaz también es interna. En la implementación de la interfaz, hago que todos los miembros que implemente sean internos. No hice una implementación explícita.
Tengo dos interfaces y dos clases que implementan esas interfaces donde esto funciona bien.
Se vería algo como esto:
internal interface IA
{
void X();
}
y entonces
internal class CA : IA
{
internal void X()
{
...
}
}
Esto funciona bien para las dos clases mencionadas anteriormente. Pero cuando trato de hacerlo con otra interfaz y clase, no funciona. De hecho, para el ejemplo anterior, aparece el error:
''WindowsFormsApplication1.CA'' no implementa el miembro de interfaz ''WindowsFormsApplication1.IA.X ()''. ''WindowsFormsApplication1.CA.X ()'' no puede implementar un miembro de interfaz porque no es público.
Me doy cuenta de que puedo hacer públicos los métodos o hacer una implementación explícita (y omitir los modificadores internos y públicos), pero simplemente estoy confundido sobre por qué funciona con las dos clases con las que funciona y, sin embargo, parece que no puedo replicar. en cualquier otro lugar.
Despachando el código un poco (porque es confidencial), este es uno de los que realmente funciona en mi proyecto.
internal interface IScanner
{
void SetHardware(Hardware hardware);
void Start();
void PauseScan();
void ResumeScan();
void Stop();
bool InScan { get; }
event ScanCompleteHandler ScanComplete;
}
Entonces tengo la clase:
internal class MyScanner : IScanner
{
internal void SetHardware(Hardware hardware)
{
...
}
internal void Start()
{
...
}
internal void Stop()
{
...
}
internal void PauseScan()
{
...
}
internal void ResumeScan()
{
...
}
internal bool InScan
{
get
{
...
}
}
internal event ScanCompleteHandler ScanComplete;
}
Para hacer las cosas aún más extrañas, creé otra clase interna llamada Temp. Luego hice que implementara la interfaz IScanner y copié y pegué la implementación de MyScanner en ella y no se compilará, dándome el error de que "no se puede implementar un miembro de la interfaz porque no es público".
¿Alguien puede explicar esta incoherencia?
Gracias
(Actualizado para corregir un error tipográfico y aclarar algunos textos)
EDITAR: Información adicional
Ejecuté el código a través del reflector y mis implementaciones se han compilado como implementaciones explícitas, aunque no son explícitas. Reflector no muestra signos de las palabras clave internas. Todo lo que puedo adivinar es que este es un tipo de error en el compilador que, por alguna razón, me permitió hacerlos internos e implícitos y que de alguna manera lo resolvió como una implementación explícita.
He revisado el código varias veces. No puedo encontrar ninguna otra explicación para eso.
Hasta donde sé, no puedes implementar métodos de interfaz internal
. Como dijiste, puedes implementarlos explícitamente, pero luego alguien puede hacerlo ((IScanner)myScanner).SetHardware(hw)
¿Estás 100% seguro de que la implementación de MyScanner
no hace algo como esto?
internal class MyScanner : IScanner
{
void IScanner.SetHardware(Hardware hardware) { this.SetHardware(hardware); }
internal void SetHardware(Hardware hardware)
{
...
}
....
}
o esto:
internal partial class MyScanner : IScanner
{
internal void SetHardware(Hardware hardware)
{
...
}
}
internal partial class MyScanner
{
void IScanner.SetHardware(Hardware hardware)
{
this.SetHardware(hardware);
}
}
Probablemente su clase "Temp" sea pública e IScanner sea interna. Esta es la razón por la cual obtienes este error. Considero que esto es muy molesto ya que se ven obligados a implementarlo explícitamente, no puede especificarlos como abstractos o virtuales. Para las cosas virtuales, me vi obligado a hacer una implementación virtual interna implícita de la misma API y luego llamar a la versión implícita desde la explícita. Feo.
Sé que ha pasado un tiempo desde que se hizo esta pregunta, pero tal vez pueda arrojar algo de luz sobre ella. De acuerdo con la especificación del lenguaje C # que se encuentra here el comportamiento que describió no debería ser posible. Debido a que bajo 20.4.2 Mapeo de interfaz se dice que la implementación es explícita o mapeada a un miembro público no estático. Entonces, o tiene otro escenario diferente al que está describiendo aquí, o encontró un error en su compilador :).
Si está implementando implícitamente una interfaz, creo que el miembro debe declararse público. En su ejemplo, CA
intenta implementar implícitamente el método X()
pero no se declara público. Si desea mantener X()
como interno, entonces debe usar la implementación explícita de la interfaz.
internal void IA.X() { /* stuff */ }
Sin embargo, también agregaré que hacer que el método X()
público no haría daño ya que la clase es interna, por lo que el miembro ya está restringido por ese modificador de acceso ... Es decir, ya es efectivamente interno ... ¡Entonces también podrías hacerlo público!