2012-01-26 12 views
29

tengo un método que utiliza la palabra clave params, así:¿Por qué pasar null a un método params da como resultado una matriz de parámetro nulo?

private void ParamsMethod(params string[] args) 
{ 
    // Etc... 
} 

Entonces, llame al método usando varias combinaciones de argumentos:

      // Within the method, args is... 
ParamsMethod();    // - a string array with no elements 
ParamsMethod(null);   // - null (Why is this?) 
ParamsMethod((string)null); // - a string array with one element: null 
ParamsMethod(null, null); // - a string array with two elements: null and null 
ParamsMethod("s1");   // - a string array with one element: "s1" 
ParamsMethod("s1", "s2"); // - a string array with two elements: "s1" and "s2" 

entiendo todos los casos, a excepción de el segundo. ¿Puede alguien explicar por qué ParamsMethod(null) hace que args sea null, en lugar de una matriz con un elemento nulo?

+0

Ahora que ya conoce la respuesta, puede trabajar en este rompecabezas. Tiene dos métodos, 'void M (object) {}' y 'void M (params object []) {}'. Llamas a 'M (nulo)'.¿Qué sobrecarga se elige, qué se le pasa y por qué? –

+2

He encontrado esto antes. Creo que acaba de renombrar uno de los métodos. :) – FishBasketGordo

Respuesta

29

Un parámetro params solo tiene como objetivo proporcionar una forma conveniente de especificar valores; aún puede pasar una referencia de matriz directamente.

Ahora, null es convertible a string[] o , por lo que ambas interpretaciones son válidas, depende de la especificación que se prefiera. Los estados de especificaciones en la sección 10.6.1.4 que:

  • El argumento dado para una matriz de parámetros puede ser una sola expresión que es implícitamente convertible al tipo matriz de parámetros. En este caso, la matriz de parámetros actúa precisamente como un parámetro de valor.

  • Alternativamente, [...]

En otras palabras, el compilador comprueba para ver si el argumento es válido como el tipo de parámetro "normal" primero, y sólo construye una matriz si absolutamente tiene que hacerlo.

+4

Además, vale la pena observar que muchos métodos que toman una matriz de parámetros también tendrán sobrecargas para (objeto), (objeto, objeto) y (objeto, objeto, objeto) - Esto es para evitar la sobrecarga de construir una matriz objeto para solo unos pocos objetos, ya que estas sobrecargas se emparejarán primero. –

3

La razón de esto es que puede pasar una matriz del tipo apropiado a un argumento params. Como null se puede convertir a cualquier tipo, y la sintaxis de la matriz tiene prioridad, obtiene null como el valor de su parámetro.

Explicitamente lanzándolo a string, por supuesto, hace que se convierta en un elemento de la matriz en lugar de la matriz en sí.

Puede probarlo y ver:

private void DoSomething(params IEnumerable[] arr) { 
    // ... 
} 

... 

DoSomething(new IEnumerable[] {new int[] {}}); // arr[0] isn't IEnumerable[], it's int[]. 

And here's an online demo.

3

Usted puede pasar una matriz a un parámetro params - de hecho, es preferible (por ejemplo si se pasa un objeto [] en una método que toma el objeto params [], es el parámetro completo, no solo el elemento individual). Null es válido como una asignación a una matriz, entonces, ese enlace gana.

Básicamente, tendrá que ser más explícito.

7

Consulte la especificación C#, sección 10.6.1.4 Las matrices de parámetros:

una matriz de parámetros permisos argumentos que deben especificarse en una de dos maneras en una invocación de método:

  • El argumento determinados para una matriz de parámetros puede ser una sola expresión que es implícitamente convertible (§6.1) al tipo de matriz de parámetros. En este caso, la matriz de parámetros actúa precisamente como un parámetro de valor.
  • Alternativamente, la invocación puede especificar cero o más argumentos para la matriz de parámetros, donde cada argumento es una expresión que es implícitamente convertible (§6.1) para el tipo de elemento de la matriz de parámetros. En este caso, la invocación crea una instancia del tipo de matriz de parámetros con una longitud correspondiente al número de argumentos, inicializa los elementos de la instancia de matriz con los valores de argumento dados, y utiliza la instancia de matriz recién creada como el argumento real.

Desde null es implícitamente convertible a string[], que será utilizado como la matriz.

Además:

Al realizar la resolución de sobrecarga, un método con una matriz de parámetros puede ser aplicable, ya sea en su forma normal o en su forma expandida (§7.5.3.1). La forma expandida de un método está disponible solo si la forma normal del método no es aplicable y solo si un método con la misma firma que el formulario expandido aún no está declarado en el mismo tipo.

que aclara que el compilador de hecho primero intenta utilizar el método con un array argumento (forma normal) antes de que intenta utilizar el argumento como una matriz elemento (forma expandida).

2

De la especificación del lenguaje:

una matriz de parámetros permite argumentos que deben especificarse en una de dos maneras en una invocación de método:

  • El argumento dado para una matriz de parámetros puede ser una expresión única que es implícitamente convertible (§6.1) al tipo de matriz de parámetros. En este caso, la matriz de parámetros actúa precisamente como un parámetro de valor.

  • Como alternativa, la invocación puede especificar cero o más argumentos para la matriz de parámetros, donde cada argumento es una expresión que es implícitamente convertible (§6.1) al tipo de elemento de la matriz de parámetros. En este caso, la invocación crea una instancia del tipo de matriz de parámetros con una longitud correspondiente al número de argumentos, inicializa los elementos de la instancia de matriz con los valores de argumento dados, y utiliza la instancia de matriz recién creada como el argumento real.

Desde null en ParamsMethod(null) se puede convertir implícitamente a (string[])null, la primera regla es la que consigue aplicado.

Cuestiones relacionadas