¿Cómo puedo devolver NULL desde un método genérico en C#?


Tengo un método genérico con este código (ficticio) (sí, soy consciente de que IList tiene predicados, pero mi código no usa IList sino alguna otra colección, de todos modos esto es irrelevante para la pregunta...)

static T FindThing<T>(IList collection, int id) where T : IThing, new()
{
    foreach T thing in collecion
    {
        if (thing.Id == id)
            return thing;
    }
    return null;  // ERROR: Cannot convert null to type parameter 'T' because it could be a value type. Consider using 'default(T)' instead.
}

Esto me da un error de compilación

" No se puede convertir el parámetro null a tipo 'T' porque podría ser un tipo de valor. Considere usar 'default(T)' en su lugar."

¿Puedo evitar este error?

 458
Author: edosoft, 2008-11-19

11 answers

Dos opciones:

  • Return default(T) lo que significa que devolverás null si T es un tipo de referencia (o un tipo de valor nullable), 0 para int, '\0' para char, etc.
  • Restrinja T para que sea un tipo de referencia con la restricción where T : class y luego devuelva null como normal
 805
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-10-01 21:00:58
return default(T);
 69
Author: Ricardo Villamil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-19 14:56:23

Simplemente puede ajustar sus restricciones:

where T : class

Entonces se permite devolver null.

 24
Author: TheSoftwareJedi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-31 19:27:54

Agregue la restricción de clase como la primera restricción a su tipo genérico.

static T FindThing<T>(IList collection, int id) where T : class, IThing, new()
 10
Author: Min,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-19 15:02:27
  1. Si usted tiene objeto entonces necesidad de encasillar

    return (T)(object)(employee);
    
  2. Si necesita devolver null.

    return default(T);
    
 6
Author: 2 revs, 2 users 86%user725388,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-11 15:15:34

La otra opción sería añadir esto al final de su declaración:

    where T : class
    where T: IList

De esa manera te permitirá devolver null.

 5
Author: BFree,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-19 15:01:37

Solución de las obras de Softwarejedi,

También puedes archivarlo usando un par de tipos de valor y nullable:

static T? FindThing<T>(IList collection, int id) where T : struct, IThing
{
    foreach T thing in collecion
    {
        if (thing.Id == id)
            return thing;
    }
    return null;
}
 2
Author: devi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-02 10:11:55

A continuación se presentan las dos opciones que puede utilizar

return default(T);

O

where T : class, IThing
 return null;
 2
Author: Jaydeep Shil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-03 19:08:34

Tome la recomendación del error... y el usuario default(T) o new T.

Tendrá que agregar una comparación en su código para asegurarse de que sea una coincidencia válida si va por esa ruta.

De lo contrario, potencialmente considere un parámetro de salida para "coincidencia encontrada".

 1
Author: Mitchel Sellers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-11 15:17:57

Aquí hay un ejemplo de trabajo para valores de retorno de enumeración nullable:

public static TEnum? ParseOptional<TEnum>(this string value) where TEnum : struct
{
    return value == null ? (TEnum?)null : (TEnum) Enum.Parse(typeof(TEnum), value);
}
 1
Author: Luke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-12 01:24:45

Otra alternativa a las 2 respuestas presentadas anteriormente. Si cambia su tipo de retorno a object, puede devolver null, mientras que al mismo tiempo cast el retorno no nulo.

static object FindThing<T>(IList collection, int id)
{
    foreach T thing in collecion
    {
        if (thing.Id == id)
            return (T) thing;
    }
    return null;  // allowed now
}
 0
Author: Jeson Martajaya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-14 12:52:00