visual valid returns remarks example comment c# arrays casting params

valid - C#params objeto[] comportamiento extraño



returns c# (3)

Teniendo en cuenta este código

namespace ConsoleApplication1 { class Program { static void Main(string[] args) { string[] strings = new string[] { "Test1", "Test2", "Test3" }; int[] ints = new int[] { 1, 2, 3, 4 }; Test(strings); Test(ints); } public static void Test(params object[] objects) { } } }

Y esta página https://msdn.microsoft.com/fr-ca/library/w5zay9db.aspx

Espero que (objeto params [] objetos) sea una matriz de un elemento con una cadena [] como primer elemento, pero cuando depuro, veo que (objeto params [] objetos) es {"Test1", "Test2 "," Test3 "}.

Sin embargo, con un int [], obtengo un objeto [] con int [] como primer elemento.

¿Es este comportamiento indefinido? ¿Depende eso de la versión .Net framework / versión Mono?


Buen hallazgo!

¿Es este comportamiento indefinido?

No. Esto es un comportamiento de diseño. Diseño extraño, pero por diseño.

¿Depende eso de la versión .Net framework / versión Mono?

No. Todas las versiones de C # tienen este comportamiento.

Esto es una consecuencia de la colisión de algunas reglas interesantes de C #.

La primera regla relevante es: un método con una matriz params puede llamarse en forma "normal" o "expandida". La forma normal es como si no hubiera "params". La forma expandida toma los parámetros y los agrupa en una matriz que se genera automáticamente. Si ambas formas son aplicables, la forma normal gana sobre la forma expandida .

Ahora, eso tal vez parezca sensato; Si tiene una matriz de objetos en la mano, es probable que desee pasar la matriz de objetos, no una matriz que contenga una matriz de objetos.

La segunda regla relevante es que C # permite la covarianza de matrices inseguras cuando el tipo de elemento es un tipo de referencia . Es decir, una matriz de cadenas se puede convertir implícitamente en una matriz de objetos. Notarás que esto tiene dos implicaciones. Primero, significa que cuando tienes una matriz de objetos, en realidad podría ser una matriz de cadenas, por lo que colocar, digamos, una tortuga en esa matriz de objetos podría causar un error de tipo. Esto es muy sorprendente! Usted espera que cada matriz de objetos pueda tomar cualquier objeto, pero eso no es cierto en C #. Algunas matrices de objetos están mintiendo.

La segunda implicación es que, puesto que poner esa tortuga en lo que realmente es una matriz de cadenas debe lanzar, significa que cada vez que se coloca algo en una matriz de tipo base, el tiempo de ejecución debe verificar que los tipos se verifiquen . Por lo tanto, las escrituras de matrices son extra caras en C # en cada escritura, por lo que la minoría cada vez más pequeña de escrituras malas puede ser atrapada.

Esto es un desastre, y es por eso que la covarianza de matrices inseguras encabeza mi lista de desafortunadas características de C #

La combinación de estas dos reglas explica tus observaciones. La matriz de cadenas se puede convertir en una matriz de objetos y, por lo tanto, el método es aplicable en forma normal.

Para la matriz de entradas, bueno, la covarianza no se aplica a los tipos de valor. Por lo tanto, la matriz de entradas no se puede convertir en una matriz de objetos, por lo que el método no es aplicable en su forma normal. Pero una matriz de entradas es un objeto, por lo que es aplicable en forma expandida.

Ver también:

¿Por qué los params se comportan así?

Su pregunta es posiblemente un duplicado de:

¿Hay alguna manera de distinguir myFunc (1, 2, 3) de myFunc (new int [] {1, 2, 3})?


No soy un experto, pero la idea de la palabra clave params era permitir la posibilidad de realizar diferentes llamadas al método independientemente de cuántos elementos tenga.

Test(object1) Test(object1, object2) Test(object1,..., objectN)

Entonces lo que estás viendo es el comportamiento normal, nada extraño. Más información en este enlace msdn

Al utilizar la palabra clave params, puede especificar un parámetro de método que tome un número variable de argumentos.

Puede enviar una lista de argumentos separados por comas del tipo especificado en la declaración del parámetro o una matriz de argumentos del tipo especificado. También puede enviar ningún argumento. Si no envía argumentos, la longitud de la lista de parámetros es cero.

No se permiten parámetros adicionales después de la palabra clave params en una declaración de método, y solo se permite una palabra clave params en una declaración de método.


public static void Test(params string[] strings) { } Test(string1) Test(string1, string2)

y así en string1 ... stringN.