2012-02-29 18 views
13

Algo en la parte posterior de este question que se pregunta por el comportamiento del parámetro out pero más centrado de por qué estos métodos utilizan TryParseout y no ref.¿Por qué métodos TryParse utiliza un parámetro de salida y no un ref

Ha habido algunos casos en los que desea inicializar un valor para el argumento antes de analizar y mantenerlo cuando el análisis falla pero realmente no le importa si falla. Sin embargo, debido al parámetro out, el valor se restablece.

Este escenario podría tener este aspecto ...

int arg = 123; 
Int32.TryParse(someString, ref arg); 

Sin embargo, debido a la out parámetro tenemos que escribirlo como este, que se mostrará más información ...

int arg; 
if(!Int32.TryParse(someString, out arg) 
{ 
    arg = 123; 
} 

que se dan cuenta que saber que el análisis fracasó puede ser muy útil; sin embargo, el uso de ref no lo excluye.

¿Por qué estos métodos TryParse usan out y no ref?

+2

Además, ¿por qué no hay un 'T TryParse (valor de cadena)' que simplemente devuelve 'default (T)' si el análisis falla? –

+0

@BennorMcCarthy: Porque no podrías distinguir entre '" 0 "' y '" o "'. – SLaks

+2

@BennorMcCarthy: Porque entonces no se puede decir la diferencia entre estos dos: "0" (analiza a 0 con éxito) y "manzanas" (analiza sin éxito, por defecto a 0). –

Respuesta

13

Porque el patrón de uso normal es exactamente el opuesto al que está describiendo.

La gente debería ser capaz de escribir

int arg; 
if (!Int32.TryParse(someString, ref arg)) { 
    Waaah; 
} 

Tenía TryParse toman un parámetro ref, esto requeriría una inicialización inútil.

La verdadera pregunta es por qué no hay un método int? int.TryParse(string).

+0

@SLaks ... cierto, cierto, ya que se agregó en .net2.0 que admite tipos con nulos. En cuanto a la inicialización inútil punto válido. Tal vez el marco puede apoyar int? ref y out sobrecargas. ahhh – aqwert

+0

La última parte de tu respuesta es exactamente a lo que estaba llegando. Un valor de retorno que se puede anular resuelve el problema de incumplimiento y, al mismo tiempo, proporciona la misma cantidad de información si es necesario. Simplemente se siente muy torpe al tener que declarar una variable para usar como un parámetro de salida. –

+1

Creo que la respuesta probablemente sea solo que el patrón existente para TryParse es anterior a los genéricos, por lo que Nullable no era una opción. –

5

Utiliza out para indicar que el parámetro no se está utilizando, solo establecido. La persona que llama se requiere para asignar un valor antes de que el método retorna:

int n; 
if (Int32.TryParse("47", out n)) { // Works fine; `n` will be set to the 
    // ..       // result of the parse. 
} 

Si utilizó ref, que tendría que inicializar el valor de antemano, que es tonto, ya que va a ser sobrescritos todos modos:

int n; 
if (Int32.TryParse("47", ref n)) { // Kablammo! `n` isn't initialized. 
    // .. 
} 

Ese es precisamente el punto de TryParse: se garantiza que tendrá un valor en el parámetro out que representa el resultado del intento de análisis. El valor de retorno de verdadero o falso indica si debe preocuparse por el resultado o ignorarlo.

+0

Semánticamente TryXXX implica que intentará hacer algo ... si falla, entonces el no debe ser modificado y conocer sobre el fracaso sea suficiente. En este caso, esperaría un argumento de referencia e iniciaría explícitamente el arg a lo que quisiera. Aunque como @SLaks señala, esto sería innecesario en la mayoría de los casos – aqwert

+0

"si falla, entonces no debería modificarse y saber sobre la falla sería suficiente" - esto solo es cierto si la mayoría de la gente quiere el resultado del análisis por defecto a algo diferente de cero. Si eso fuera cierto, entonces 'default (T)' para enteros no debería ser cero. Pero lo es, entonces lo que pides es una contradicción. –

3

Esto se debe a que un parámetro out se ajusta mejor a lo que hace el método.

Si utilizó un parámetro ref, entonces tiene para proporcionar una entrada al método. Esto no funcionaría:

int arg; 
if (Int32.TryParse(someString, ref arg)) { // error - variable is not initialsed 

El método no espera ninguna entrada en el parámetro de valor, si tendría que proporcionar un valor de entrada, no es obvio lo que sería, o como funciona eso sería utilizado.

0

En mi experiencia de todos modos, hay muchas más ocasiones en las que no desea preocuparse por la inicialización, que cuando desea proporcionar un valor predeterminado. Parse fue diseñado con esto en mente.

La pregunta es buena, y no creo que haya un problema grave con un enfoque u otro. El equipo de .NET eligió el enfoque de salida, ya que no podían usar ambos sin agregar un método diferente a int, lo que sería desagradablemente redundante.

Cuestiones relacionadas