2010-08-18 8 views
7

Tengo problemas para entender por qué las matrices en C# son covariantes y qué beneficios puede traer esta covarianza. Considere el siguiente ejemplo de código trivial:¿Por qué las matrices C# son covariantes y qué beneficios aporta?

object[] myArray = new string[1]; 
myArray[0] = 1; 

Este código se compila bien, pero será sin contemplaciones y tal como era de esperar explotar en tiempo de ejecución.

Si trato de intentar lo mismo usando genéricos, el compilador se quejaba y me daría cuenta de mi estupidez en una etapa temprana, así que mi pregunta es esta: ¿Por qué el compilador C# permite esta covarianza con matrices y además , ¿Cuáles son los beneficios potenciales?

Respuesta

12

Eric Lippert dice:

U por desgracia, este tipo particular de covarianza está roto. Se agregó al CLR porque Java lo requiere y los diseñadores de CLR querían poder admitir lenguajes similares a Java. Luego subimos y lo agregamos a C# porque estaba en el CLR. Esta decisión fue bastante controvertida en ese momento y no estoy muy contento con ella, pero no hay nada que podamos hacer ahora.

4

Eric Lippert tiene una valoración crítica acerca de este (en realidad una larga serie sobre 'variación', 11 partes creo)

http://blogs.msdn.com/b/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance.aspx

y algunas cosas más interesante

http://blogs.msdn.com/b/ericlippert/archive/2009/09/24/why-is-covariance-of-value-typed-arrays-inconsistent.aspx

+3

mquander gana por citar el blog en lugar de simplemente vincularlo. –

+1

@Jon B - y para citar el bit _relevant_. – Oded

+0

Gracias por los enlaces a información adicional. Muy útil. – nukefusion

1

Hay muchas situaciones en las que el código moverá o copiará elementos entre las ranuras de una matriz. Siempre que Arr sea una matriz unidimensional con al menos dos elementos, el siguiente código funcionará independientemente del tipo de Arr o de los elementos contenidos en él.

Object temp = Arr[1]; 
Arr[1] = Arr[0]; 
Arr[0] = temp; 

Este código será ineficaz si Arr es un tipo de valor, pero desde temp se lee de la matriz, el tipo de la matriz se garantiza que sea capaz de mantener un valor tal. El código tendrá que encajonar y desempaquetar elementos de tipo valor, y por lo tanto será ineficiente con dichos tipos, pero funcionará independientemente.

Tenga en cuenta que al hacer que las matrices sean covariantes es una forma de permitir que cosas como los métodos de clasificación funcionen en tipos de matriz arbitrarios, no es el único. Otro enfoque sería tener System.Array incluir algunos métodos y propiedades cuyos parámetros no tienen relación con el tipo de elemento subyacente. Por ejemplo, podría incluir algunos métodos simples como Swap, CopyItem y Roll, y posiblemente métodos para realizar permutaciones más complejas dada una lista de índices. Tenga en cuenta que, a diferencia del código que se muestra arriba, un tipo como Int[] puede anular su método Swap de tal manera que se evite el boxeo y el desempaquetado.

Cuestiones relacionadas