2010-09-09 13 views
12

Practicaba genéricos. Considere un método de pila a continuación. Cuál es la mejor forma de verificar errores que no sea arrojar excepciones en un método genérico. ¿Qué sucede si quiero devolver algún resultado en este método?Tipo genérico de devolución en C#

public T pop() 
{ 
    if (top >= 0) 
     return arr[top--]; 
    return -1 or null; 
} 

Respuesta

15

La única cosa que podría hacer es volver default(T), que es el valor predeterminado para el tipo T (null para los tipos de referencia, cero para los tipos integrales y campos reducidos a cero objeto para otros tipos de valores). Sin embargo, esto generalmente es una mala idea ya que no tendrá forma de distinguir entre un 0 que apareció o un 0 que indica un error. Generalmente, las excepciones son la mejor manera de hacerlo en estos casos, pero también puede cambiar su método de la siguiente manera:

public bool TryPop(out T value) 
{ 
    if (top >= 0) 
    { 
     value = arr[top--]; 
     return true; 
    } 
    value = default(T); 
    return false; 
} 
+0

¡Gracias a todos! Se necesitaba una alternativa a las excepciones. No sabía sobre el incumplimiento (T). –

+0

Hmmm, una función que cambia un parámetro ... qué poco funcional (sí, uso TryParse pero trato de evitar cosas que se llaman a sí mismas funciones pero en realidad no lo son). –

+0

@Edgar no lo ve como cambiar un parámetro, véalo como un segundo valor de retorno. No es peor que devolver un 'Tuple '. Lo que le temes son los parámetros 'ref'. – Trillian

6

Usted podría hacer return default(T), que devolverá 0 tipos de valores inicializados (ex. Todos los tipos numéricos serán inicializados a 0), y nulo para los tipos de referencia.

+0

+1, debe agregar un bit que devuelve 0 valores inicializados para todos los tipos de estructura (básicamente expanda la parte de los tipos numéricos) – JaredPar

+0

Esto es una mala idea porque entonces no puede distinguir entre un objeto que se saltó cuyo valor es 'default (T)' y un error señalado al devolver 'default (T)'. – Trillian

+0

@JaredPar Cierto, hecho. –

0

Su pregunta no está clara. El error comprobando se puede hacer de la misma manera que siempre, atrapando excepciones. Recaudando los errores generalmente se deben hacer lanzando excepciones. Para eso están para eso, después de todo.

Si usted quiere volver null se puede hacer eso, pero entonces usted tiene que asegurarse de que el tipo T es una clase, no una estructura, de este modo:

public T pop() 
    where T: class 
{ 
    ... 
} 
1

Parece que su pregunta realmente tiene dos partes

La primera parte es cómo proporcionar un valor predeterminado si no hay uno disponible. Como han señalado otras personas, la expresión C# default(T) funcionará para este escenario. Devuelve null para los tipos de referencia y 0 valores inicializados para las estructuras.

La segunda parte es la mejor forma de manejar el caso de error que no sea arrojar una excepción. API Collection tienden a utilizar el patrón TryXXX para este tipo de escenario

bool TryPop(out T value) { 
    if (top >= 0) { 
    value = arr[top--]; 
    return true; 
    } 
    value = default(T); 
    return false; 
} 
0

Si usted quiere ser capaz de volver nula cuando la pila está vacía puedes intentar algo como esto:

class GenericStack<T> 
{ 
    T[] arr; 
    int top; 

    public T pop() 
    { 
     if (top >= 0) 
      return arr[top--]; 
     return default(T); 
    } 
} 

Y luego puede usar usar de esta manera:

 var stack = new GenericStack<int?>(); 

     var res = stack.pop(); // res will be null 

Observe que el objeto de la pila es del tipo int? para que podamos devolver nulos.

0

enfoque directo (genéricos de uso y valor de retorno o nula)

class DemoClass<T> where T : struct 
{ 
    public T? PopValueOrNull() 
    { 
    if (this._top >= 0) { 
     return this._arr[this._top--]; 
     } 

     return null; 
    } 
} 
+0

bien, me olvido "donde T: struct" :) ... espera un segundo ... añadido – Andrey

1

vine aquí en busca de una solución a un problema ligeramente diferente, con la participación de un método estático que toma dos matrices genéricas y devuelve un nuevo genérico formación. Como mi método era estático, no podía usar el ejemplo, excepto como inspiración. En cambio, desarrollé la siguiente solución.

T [ ] raMerged = (T [ ]) alMerged.ToArray (typeof (T)); 
return raMerged; 

En el fragmento anterior, alMerged es una ArrayList de objetos genéricos T.

Esto cumple las condiciones del contrato especificado por la firma del método, que es la siguiente.

public static T [ ] MergeNewItemsIntoArray<T> (
T [ ] paMasterList , 
T [ ] paNewItems) 
where T : IComparable , new () 

En la firma, la cláusula where ilustra mi resolución de otro problema que he encontrado en varios hilos, ninguno de los cuales están dirigidos directamente a esta pregunta. Sin embargo, con suerte, esto ayudará al menos a otra alma.

Cuestiones relacionadas