Cómo convertir C # nullable int a int

484

¿Cómo convierto un nulo inten un int? Supongamos que tengo 2 tipos de int como a continuación:

int? v1;  
int v2; 

Quiero asignarle v1el valor v2. v2 = v1;provocará un error ¿Cómo convierto v1a v2?

KentZhou
fuente
¿Cuál es el comportamiento deseado cuando v1es null?
Solomon Ucko

Respuestas:

637

Las otras respuestas hasta ahora son todas correctas; Solo quería agregar uno más que sea un poco más limpio:

v2 = v1 ?? default(int);

Cualquiera Nullable<T>es implícitamente convertible a su T, SIEMPRE que la expresión completa que se evalúa nunca puede dar como resultado una asignación nula a un ValueType. Entonces, el operador de fusión nula ??es solo azúcar de sintaxis para el operador ternario:

v2 = v1 == null ? default(int) : v1;

... que a su vez es sintaxis de azúcar para un if / else:

if(v1==null)
   v2 = default(int);
else
   v2 = v1;

Además, a partir de .NET 4.0, Nullable<T>tiene un método "GetValueOrDefault ()", que es un getter nulo seguro que básicamente realiza la fusión nula que se muestra arriba, por lo que esto también funciona:

v2 = v1.GetValueOrDefault();
KeithS
fuente
44
¿Es default(int)realmente necesario? ¿Qué tiene de malo un simple 0?
Cole Johnson
44
Funcionaría para este ejemplo, pero en el caso general se recomienda usar defaultdonde sea apropiado. El cero no siempre es válido como valor, mucho menos el predeterminado, por lo que si lo reemplaza intcon un genérico T, encontrará que mi código funciona mientras que el cero no. En algunas versiones futuras del framework, defaulttambién puede volverse sobrecargable; si eso sucede, el código que usa el valor predeterminado podrá aprovechar fácilmente, mientras que las asignaciones explícitas nulas o nulas tendrán que cambiarse.
KeithS
55
Esto debería llegar a la cima: .NET 4.0, Nullable <T> tiene un "GetValueOrDefault ()"
RandomHandle
¡Gracias por volver a editarlo con GetValueOrDefault!
CindyH
Es posible que desee tener cuidado con DateTime cuando usa el valor predeterminado. Esto podría insertar la fecha predeterminada en lugar de vacía.
Rancho Camal
168

Me gusta esto,

if(v1.HasValue)
   v2=v1.Value
Srinivas Reddy Thatiparthy
fuente
92

Puede usar la propiedad Value para la asignación.

v2 = v1.Value;
e36M3
fuente
8
Además, si no está seguro de si v1 contiene nulo, puede usar el operador de fusión nula para establecer un valor de reserva. Por ejemplo, v2 = v1 ?? 0;
Arjen
12
Y asegúrese de verificar v1.HasValueprimero.
Yuck
3
MSDN dice que esto arrojará una excepción si v1es así null. En mi opinión, esta no es una respuesta correcta.
ventiseis
66
@ventiseis Creo que es un comportamiento deseable: me sorprende que muchas de las otras respuestas estén bien con la conversión silenciosa de un valor nulo a 0. Si está asignando un tipo anulable a un tipo no anulable, debe estar seguro de que el valor no es realmente nulo. OP no dijo "Quiero asignar v1 a v2, o 0 si v1 es nulo", pero eso es lo que todos parecían asumir
Michael Mrozek
82

Todo lo que necesitas es..

v2= v1.GetValueOrDefault();
la estrella
fuente
49

Si sabe que v1tiene un valor, puede usar la Valuepropiedad:

v2 = v1.Value;

El uso del GetValueOrDefaultmétodo asignará el valor si hay uno; de lo contrario, el valor predeterminado para el tipo o el valor predeterminado que especifique:

v2 = v1.GetValueOrDefault(); // assigns zero if v1 has no value

v2 = v1.GetValueOrDefault(-1); // assigns -1 if v1 has no value

Puede usar la HasValuepropiedad para verificar si v1tiene un valor:

if (v1.HasValue) {
  v2 = v1.Value;
}

También hay soporte de idioma para el GetValueOrDefault(T)método:

v2 = v1 ?? -1;
Guffa
fuente
No debe usar el valor sin verificar primero si hay un valor. Utilizar el ?? operador en su lugar.
Peter
45

No puede hacerlo si v1 es nulo, pero puede verificarlo con un operador.

v2 = v1 ?? 0;
Arturo Martinez
fuente
28

GetValueOrDefault()

recupera el valor del objeto. Si es nulo, devuelve el valor predeterminado de int, que es 0.

Ejemplo:

v2= v1.GetValueOrDefault();

Aniket Sharma
fuente
21

Si el valor predeterminado para un tipo dado es un resultado aceptable:

if (v1.HasValue)
    v2 = v1.GetValueOrDefault();

Si desea un valor predeterminado diferente cuando el resultado no está definido:

v2 = v1.GetValueOrDefault(255);    // or any valid value for int in place of 255

Si solo desea que se devuelva el valor (no importa si el método falló o no):

v2 = v1.GetValueOrDefault();


.NET 4.7.2 .: GetValueOrDefault()devuelve el valor del campo sin ninguna comprobación.

GrzegorzF
fuente
15

En lo que a mí respecta, la mejor solución es usar el GetValueOrDefault()método.

v2 = v1.GetValueOrDefault();
Masoud Darvishian
fuente
este fue el más útil para mí
Liakat
11

La conversión de int nullable a int se puede hacer así:

v2=(int)v1;
Krishna shidnekoppa
fuente
99
Si v1 es nulo, esto provocará una InvalidOperationException.
MungeWrath
10

es posible con v2 = Convert.ToInt32(v1);

Rdo
fuente
Esto funcionará técnicamente, pero otras técnicas como HasValue / Value o GetValueOrDefault se ejecutan de manera mucho más eficiente.
Brandon Barkley
9

Podrías hacerlo

v2 = v1.HasValue ? v1.Value : v2;
Panda de fuego
fuente
9

Una conversión simple entre v1y v2no es posible porque v1tiene un dominio de valores mayor que v2. Es todo lo que v1puede aguantar más el nullestado. Para realizar la conversión, debe indicar explícitamente qué valor intse utilizará para asignar el nullestado. La forma más simple de hacer esto es el ??operador

v2 = v1 ?? 0;  // maps null of v1 to 0

Esto también se puede hacer en forma larga

int v2;
if (v1.HasValue) {
  v2 = v1.Value;
} else {
  v2 = 0;
}
JaredPar
fuente
9

Dependiendo de su contexto de uso, puede usar la función de coincidencia de patrones de C # 7:

int? v1 = 100;
if (v1 is int v2)
{
    Console.WriteLine($"I'm not nullable anymore: {v2}");
}

EDITAR:

Dado que algunas personas están votando sin dejar una explicación, me gustaría agregar algunos detalles para explicar la justificación para incluir esto como una solución viable.

  • La coincidencia de patrones de C # 7 ahora nos permite verificar el tipo de un valor y emitirlo implícitamente. En el fragmento anterior, la condición if solo pasará cuando el valor almacenado v1sea ​​compatible con el tipo para el tipo v2, que en este caso lo es int. Se deduce que cuando el valor para v1es null, la condición if fallará ya que nulo no puede asignarse a un int. Más adecuadamente, nullno es un int.

  • Me gustaría destacar que esta solución puede no ser siempre la mejor opción. Como sugiero, creo que esto dependerá del contexto de uso exacto del desarrollador. Si ya tiene un int?y desea operar condicionalmente en su valor si y solo si el valor asignado no es nulo (este es el único momento en que es seguro convertir un int anulable en un int regular sin perder información), entonces La coincidencia de patrones es quizás una de las formas más concisas de hacer esto.

Nicholas Miller
fuente
La necesidad de introducir un nuevo nombre de variable es lamentable, pero esta es la mejor solución (la más segura) si no hay un valor predeterminado, porque no hay riesgo de refactorizar accidentalmente sus HasValuecheques.
minexew
Simplemente no veo ninguna ventaja para este método sobre v1.HasValue como la comprobación y luego v1.Value para acceder al valor subyacente. No lo rechazaría, pero creo que este problema ya se ha resuelto y una nueva técnica no agrega mucha claridad al problema. También lo comparé como 8-9% más lento.
Brandon Barkley
Gracias por compararlo, ¡es bueno saberlo! De cualquier manera que lo mire, la diferencia es marginal en el mejor de los casos (a menos que haga esto en un área crítica, supongo). Considero que esto es más "conciso" o posiblemente "idiomático", ya que se basa en azúcares de sintaxis en el lenguaje en lugar de API. Es un poco subjetivo, pero quizás sea "más fácil de mantener". Aunque realmente, me gusta este enfoque más que confiar en un valor predeterminado, como sugieren muchas otras respuestas.
Nicholas Miller
3

Asignará el valor de v1a v2si no es nulo, de lo contrario tomará un valor predeterminado como cero.

v2=v1??0

O debajo está la otra forma de escribirlo.

v2 = v1.HasValue?v1:0
sagar
fuente
1

En C # 7.1 y versiones posteriores, se puede inferir el tipo usando el defaultliteral en lugar del defaultoperador para que se pueda escribir de la siguiente manera:

v2 = v1 ?? default;
akesfeden
fuente
-1
 int v2= Int32.Parse(v1.ToString());
mohammad qavizi
fuente
55
Si bien este código puede responder la pregunta, proporcionar un contexto adicional con respecto a por qué y / o cómo responde la pregunta mejora su valor a largo plazo.
xiawi
1
Es mejor usar la forma de "mejor práctica" para desenvolver opciones, en lugar de usar trucos disimulados. Ver docs.microsoft.com/en-us/dotnet/csharp/language-reference/… para referencia
lorg
Al contestar una pregunta de ocho años con quince respuestas existentes, es importante explicar qué nuevo aspecto de la pregunta aborda su respuesta y observar si el paso del tiempo ha cambiado la respuesta. Las respuestas de solo código casi siempre se pueden mejorar mediante la adición de alguna explicación.
Jason Aller