2010-05-03 4 views
6

Si uno pudiera poner una matriz de punteros a estructuras secundarias dentro de estructuras inseguras en C# como podría hacerlo en C, construir estructuras de datos complejas sin la sobrecarga de tener un objeto por nodo sería mucho más fácil y menos hundido, como así como sintácticamente más limpio y mucho más legible.¿Cuál es la razón subyacente para no poder poner matrices de punteros en estructuras inseguras en C#?

¿Existe una profunda razón arquitectónica por la cual las matrices fijas dentro de las estructuras inseguras solo pueden estar compuestas de "tipos de valores" y no de punteros?

Supongo que solo tener punteros explícitamente nombrados dentro de las estructuras debe ser una decisión deliberada de debilitar el lenguaje, pero no puedo encontrar ninguna documentación sobre por qué esto es así, o el razonamiento para no permitir matrices de punteros dentro de las estructuras, ya que supondría que al recolector de basura no le importa lo que está pasando en las estructuras marcadas como inseguras.

Digital Mars 'D maneja estructuras y punteros con elegancia en comparación, y me falta no poder desarrollar rápidamente estructuras de datos sucintas; Al hacer referencias abstractas en C#, parece que se ha eliminado una gran cantidad de poder del lenguaje, a pesar de que los punteros todavía están allí, al menos en un sentido de comercialización.

Tal vez sea incorrecto esperar que los idiomas se vuelvan más poderosos en la representación de estructuras de datos complejas de manera eficiente con el tiempo.

Respuesta

2

Estoy adivinando, pero podría tener que ver con diferentes tamaños de puntero para diferentes plataformas de destino. Parece que el compilador de C# está utilizando el tamaño de los elementos directamente para los cálculos de índice (es decir, no hay soporte CLR para calcular índices de búferes de tamaño fijo ...)

De todos modos se puede utilizar una gran variedad de ulong s y emitir los punteros a ella:

unsafe struct s1 
{ 
    public int a; 
    public int b; 
} 

unsafe struct s 
{ 
    public fixed ulong otherStruct[100]; 
} 

unsafe void f() { 
    var S = new s(); 
    var S1 = new s1(); 
    S.otherStruct[4] = (ulong)&S1; 
    var S2 = (s1*)S.otherStruct[4]; 
} 
4

Una razón muy simple: dotNET tiene un colector de basura compactando basurero. Mueve las cosas. Por lo tanto, incluso si pudiera crear arreglos de ese tipo, tendría que pin cada bloque asignado y el sistema se ralentizaría.

Pero está intentando optimizar según una suposición. La asignación y limpieza de objetos en dotNET está altamente optimizada. Entonces, primero escriba un programa que funcione y luego use un generador de perfiles para encontrar sus cuellos de botella. Lo más probable es que no sea la asignación de sus objetos.

Editar, para responder a la última parte:

Tal vez me equivoque esperar idiomas a ser más poderoso en la representación de estructuras complejas de datos de manera eficiente lo largo del tiempo.

Creo que C# (o cualquier lenguaje administrado) es mucho más poderoso en la representación de estructuras de datos complejos (eficientemente). Cambiando de punteros de bajo nivel a referencias recogidas de basura.

+0

Lo perfilador me recomiendan? – cons

+2

Esa no puede ser la razón, ya que puedes usar punteros para otras estructuras inseguras dentro de estructuras inseguras (no hay problema con crear una estructura de árbol binario de esa manera ...) La restricción se aplica solo a matrices dentro de estructuras inseguras (llamadas tampones de tamaño), y la razón para esto no es obvia en mi opinión (Consulte mi respuesta para una posible explicación) – MartinStettner

+1

@cons: Vea esta pregunta: http://stackoverflow.com/questions/3927/ –

1

Poner una matriz fija de punteros en una estructura lo convertiría rápidamente en un mal candidato para una estructura. El límite de tamaño recomendado para una estructura es de 16 bytes, por lo que en un sistema x64 solo cabría dos punteros en la matriz, lo cual es bastante inútil.

Debe usar clases para estructuras de datos complejas; si utiliza estructuras, su uso es muy limitado. Por ejemplo, no podría crear una estructura de datos en un método y devolverla, ya que contendría punteros a estructuras que ya no existen, ya que se asignaron en el marco de pila del método.

+0

Interesante. ¿Puedes dar un enlace a algunos artículos o explicar un poco por qué 16 bytes? –

+0

@Alexander: es lo que Microsoft dice en sus directrices: http://msdn.microsoft.com/en-us/library/y23b5415%28VS.71%29.aspx – Guffa

+0

El umbral de tamaño donde una clase será más eficiente que una struct varía considerablemente con los patrones de uso. Las clases inmutables de menos de 16 bytes muy pocas veces serán más eficientes que las estructuras fuera de los escenarios artificiales, pero con muchos patrones de uso, incluso las estructuras "grandes" (64-256 bytes) pueden superar a las clases. Para algunos patrones de uso, el "margen de ganancia" para estructuras en realidad aumenta con cargas útiles más grandes (siempre que no sean tan grandes como para bloquear la pila). – supercat

Cuestiones relacionadas