una puede programacion nombres métodos miembros instanciar espacio error ejemplos directamente contener como comandos codigos clases clase campos aprender c# namespaces circular-dependency circular-reference

puede - ¿Por qué se permite la dependencia circular con espacios de nombres en c#?



instanciar una clase c# (2)

Sus suposiciones de que las asambleas no pueden hacer una referencia cruzada entre sí son incorrectas. Es difícil configurarlo, y no es fácil hacerlo a través de Visual Studio, IIRC, pero es factible.

Primero, creamos 3 archivos de texto:

A.cs :

using B; namespace A { public class AA { public AA(BB val) { } } }

B.cs :

using A; namespace B { public class BB { public BB(AA val) { } } }

Y, A_prime.cs :

namespace A { public class AA { public AA() { } } }

Tenga en cuenta que estas clases no son útiles ni utilizables. Solo para demostrar el punto, que es que tenemos dos fuentes posibles para A , una en la que rescindimos o "solucionamos" nuestra necesidad de una dependencia de B , y la otra donde no lo hacemos.

Luego compilamos:

csc /out:A.dll /target:library A_prime.cs csc /out:B.dll /target:library /reference:A.dll B.cs csc /out:A.dll /target:library /reference:B.dll A.cs

Resultado final: tenemos dos conjuntos que se cruzan entre sí 1 .

Del mismo modo, dentro del propio marco .NET, tenemos muchas referencias System.dll : System.dll , System.Xml.dll y System.Configuration.dll son referencias cruzadas entre sí. Aunque probablemente tengan una configuración de compilación más sofisticada que la anterior, utilizando un solo archivo de origen y símbolos para realizar el arranque, en lugar de separar los archivos de origen.

Y, por último, para abordar los espacios de nombres: los espacios de nombres son una agrupación lógica de funcionalidades. Varios ensamblados pueden contribuir tipos a un solo espacio de nombres. Un solo ensamblaje puede contribuir tipos a múltiples espacios de nombres. No existe una razón lógica por la que los tipos dentro de múltiples espacios de nombres no puedan referirse el uno al otro en ambas direcciones.

1 Esto funciona siempre que la versión de csc que utiliza de forma predeterminada asigne un número de versión de 0.0.0.0 si no hay ningún atributo AssemblyVersion en la fuente. Si ese no es el caso para una instancia particular de csc (me parece recordar que era diferente en algunos más antiguos), puede necesitar aplicar este atributo para asegurar que las dos compilaciones de A.dll produzcan un ensamblado con la misma identidad.

Del mismo modo, detalles como el nombramiento fuerte pueden hacer que el proceso sea más laborioso.

2 referencia "Little-r", no referencia "Big-r". Por ejemplo, diferentes tipos simplemente usando el uno al otro. No referencia en "¿Qué es una referencia en C #?" condiciones.

En c # se le permite tener una declaración en el archivo a.cs (que tiene espacio de nombre de MyApp.A):

using MyApp.B;

mientras que el archivo b.cs (que tiene el espacio de nombre de MyApp.B) ya tiene la declaración

using MyApp.A;

Si existiría una dependencia similar en diferentes dll (donde a.dll tiene una referencia a b.dll y viceversa) no se permitiría debido a un error de dependencia circular, entonces ¿por qué está permitido con espacios de nombres (y el compilador no lo hace? incluso producir una advertencia)? ¿No es un olor a código hacerlo de todos modos?


Damien_The_Unbeliever escribió Namespaces son una agrupación lógica de funcionalidades .

Hans Passat escribió Namespace no es más que una simple pista para el compilador .

Me gustaría detallar que realmente depende de lo que consideras que es un componente en tu código base. Un componente es un grupo de tipos. Un componente puede engendrar uno o varios espacios de nombres definidos en uno o varios conjuntos. Lo importante es que no hay un ciclo de dependencia entre los componentes. Debido a que un componente es una unidad de desarrollo , y si los componentes A y B se usan mutuamente, constituyen una unidad de desarrollo mayor , no pueden desarrollarse independientemente, forman un súper componente o, en otras palabras, esta es la raíz del código de spaghetti .

Para responder a su pregunta, ¿por qué se permite la dependencia circular con espacios de nombres en c #? la declaración implícita detrás de su pregunta es que los espacios de nombres se usan para definir componentes lógicos . Pero el espacio de nombres también se puede usar para evitar la colisión del nombre de tipo, para presentar las clases de una API pública de una manera estructurada, para filtrar un conjunto de métodos de extensión ... Por lo tanto, creo que la respuesta es que el diseñador C # ciertamente no quería restringe el concepto de espacio de nombres solo para la componente lógica .

Como nota al margen, muchos desarrolladores están utilizando el concepto de proyecto / ensamblaje para definir componentes. En mi humilde opinión, esto es incorrecto porque el ensamblaje es un concepto físico que viene con costo y mantenimiento (control de versiones, implementación, compilación, carga CLR dinámica ...). El ensamblaje como concepto físico se debe usar por razones físicas (como unidad de despliegue, unidad de API, plugin impl, código / separación de prueba ...). Escribí dos libros blancos sobre esta asamblea contra el espacio de nombres versus el tema del componente si puede interesarle.

¿No es un olor a código hacerlo de todos modos?

En mi opinión lo es, porque si un ensamblaje grande contiene muchos espacios de nombres con ciclos de dependencia, uno no tiene forma de intentar comprender la arquitectura general desde el código. Trabajo en un analizador estático .NET llamado NDepend que puede verificar ciclos de dependencia de espacios de nombres y presentar resultados a través del gráfico de dependencia y la matriz de dependencia . Tenemos más de 400 espacios de nombres y nos complace mantenerlos todos en capas adecuadamente en una docena de ensamblajes. La matriz de dependencia ofrece una forma práctica de visualizar la estructura del espacio de nombres en capas de un vistazo.