Como converter int n anulável em int

484

Como faço para converter um anulável intem um int? Suponha que eu tenha 2 tipos de int como abaixo:

int? v1;  
int v2; 

Eu quero atribuir v1o valor de v2. v2 = v1;causará um erro. Como faço v1para converter para v2?

KentZhou
fonte
Qual é o comportamento desejado quando v1é null?
Solomon Ucko

Respostas:

637

As outras respostas até agora estão todas corretas; Eu só queria adicionar mais um pouco mais limpo:

v2 = v1 ?? default(int);

Qualquer um Nullable<T>é implicitamente conversível T, desde que a expressão inteira que está sendo avaliada nunca possa resultar em uma atribuição nula a um ValueType. Portanto, o operador coalescente nulo ??é apenas açúcar de sintaxe para o operador ternário:

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

... que por sua vez é açúcar de sintaxe para um if / else:

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

Além disso, a partir do .NET 4.0, Nullable<T>possui um método "GetValueOrDefault ()", que é um getter com segurança nula que basicamente executa a coalescência nula mostrada acima, portanto, isso também funciona:

v2 = v1.GetValueOrDefault();
KeithS
fonte
4
É default(int)realmente necessário? O que há de errado com um simples 0?
Cole Johnson
4
Funcionaria para este exemplo, mas, no caso geral, é recomendável usar defaultonde for apropriado. Zero nem sempre é válido como um valor, muito menos o padrão, portanto, se você substituirint por um genérico, Tverá que meu código funciona enquanto zero não. Em alguma versão futura do framework, defaulttambém pode se tornar sobrecarregável; se e quando isso acontecer, o código usando o padrão poderá tirar vantagem facilmente, enquanto as atribuições nulas ou zero explícitas precisarão ser alteradas.
Keiths
5
Isso deve subir para o topo: .NET 4.0, Nullable <T> possui um "GetValueOrDefault ()"
RandomHandle
Obrigado por voltar para editá-lo com GetValueOrDefault!
CindyH
Você pode ter cuidado com o DateTime ao usar o padrão. Isso pode inserir a data padrão em vez de vazia.
Ranch Camal
168

Como isso,

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

Você pode usar a propriedade Value para atribuição.

v2 = v1.Value;
e36M3
fonte
8
Além disso, se você não tiver certeza se a v1 contém nulo, pode usar o operador coalescente para definir um valor de fallback. Por exemplo, v2 = v1 ?? 0;
Arjen
12
E não deixe de conferir v1.HasValueprimeiro.
Yuck
3
O MSDN diz que isso gerará uma exceção se ov1 houver null. Na minha opinião, esta não é uma resposta correta.
ventiseis
6
@ventiseis Eu acho que esse é um comportamento desejável - Estou surpreso que muitas das outras respostas sejam aceitáveis ​​ao converter silenciosamente um nulo para 0. Se você estiver atribuindo um tipo nulo a um tipo não nulo, deve ter certeza de que o valor não é realmente nulo. O OP não disse "Quero atribuir v1 a v2 ou 0 se v1 for nulo", mas é o que todos pareciam assumir
Michael Mrozek
82

Tudo o que você precisa é..

v2= v1.GetValueOrDefault();
a estrela
fonte
49

Se você sabe que v1tem um valor, pode usar a Valuepropriedade:

v2 = v1.Value;

O uso do GetValueOrDefaultmétodo atribuirá o valor se houver um, caso contrário, o padrão para o tipo ou um valor padrão que você especificar:

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

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

Você pode usar a HasValuepropriedade para verificar se v1tem um valor:

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

Também há suporte ao idioma para o GetValueOrDefault(T)método:

v2 = v1 ?? -1;
Guffa
fonte
Você não deve usar o valor sem verificar primeiro se há um valor. Use o ?? operador em vez disso.
Peter
45

Você não pode fazer isso se a v1 for nula, mas você pode verificar com um operador.

v2 = v1 ?? 0;
Arturo Martinez
fonte
28

GetValueOrDefault()

recupera o valor do objeto. Se for nulo, ele retornará o valor padrão de int, que é 0.

Exemplo:

v2= v1.GetValueOrDefault();

Aniket Sharma
fonte
21

Se o valor padrão para um determinado tipo for um resultado aceitável:

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

Se você desejar um valor padrão diferente quando o resultado for indefinido:

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

Se você deseja apenas o valor retornado (não importa se o método falhou ou não):

v2 = v1.GetValueOrDefault();


.NET 4.7.2 .: GetValueOrDefault()retorna o valor do campo sem nenhuma verificação.

GrzegorzF
fonte
15

Para mim, a melhor solução é usar o GetValueOrDefault()método

v2 = v1.GetValueOrDefault();
Masoud Darvishian
fonte
este foi o melhor útil para mim
Liakat
11

A conversão int anulável em int pode ser feita da seguinte maneira:

v2=(int)v1;
Krishna shidnekoppa
fonte
9
Se v1 for nulo, isso causará uma InvalidOperationException.
MungeWrath 17/02
10

é possível com v2 = Convert.ToInt32(v1);

Rev
fonte
Isso funcionará tecnicamente, mas outras técnicas, como HasValue / Value ou GetValueOrDefault, são executadas com muito mais eficiência.
Brandon Barkley
9

Você poderia fazer

v2 = v1.HasValue ? v1.Value : v2;
Panda de fogo
fonte
9

Uma conversão simples entre v1e v2não é possível porque v1possui um domínio de valores maior que v2. É tudo o que v1pode aguentar mais o nullestado. Para converter, você precisa declarar explicitamente em que valor intserá usado para mapear o nullestado. A maneira mais simples de fazer isso é o ??operador

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

Isso também pode ser feito de forma longa

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

Dependendo do contexto de uso, você pode usar o recurso de correspondência de padrões do C # 7:

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

EDITAR:

Como algumas pessoas estão votando sem deixar uma explicação, eu gostaria de adicionar alguns detalhes para explicar a lógica de incluir isso como uma solução viável.

  • A correspondência de padrões do C # 7 agora nos permite verificar o tipo de um valor e convertê-lo implicitamente. No snippet acima, a condição if somente passará quando o valor armazenado v1for compatível com o tipo do tipo for v2, que nesse caso é int. Daqui resulta que, quando o valor for v1for null, a condição if falhará, pois null não pode ser atribuído a um int. Mais corretamente, nullnão é um int.

  • Gostaria de destacar que o fato de que essa solução nem sempre é a melhor opção. Como sugiro, acredito que isso dependerá do contexto de uso exato do desenvolvedor. Se você já possui um int?e deseja operar condicionalmente em seu valor se e somente se o valor atribuído não for nulo (este é o único momento em que é seguro converter um int nulo em um int regular sem perder informações), a correspondência de padrões é talvez uma das maneiras mais concisas de fazer isso.

Nicholas Miller
fonte
A necessidade de introduzir um novo nome de variável é lamentável, mas esta é a melhor solução (mais segura) se não houver valor padrão, porque não há risco de refatorar acidentalmente suas HasValueverificações.
minexew
Eu simplesmente não vejo nenhuma vantagem nesse método sobre v1.HasValue como a verificação e, em seguida, v1.Value para acessar o valor subjacente. Eu não descartaria isso, mas acho que esse problema já foi resolvido e uma nova técnica não adiciona muita clareza ao problema. Eu também o comparei como 8-9% mais lento.
Brandon Barkley
Obrigado por compará-lo, é bom saber! De qualquer maneira, a diferença é marginal, na melhor das hipóteses (a menos que você faça isso em alguma área crítica do tempo, suponho). Considero isso mais "conciso" ou possivelmente "idiomático", pois se baseia em açúcares de sintaxe inseridos na linguagem em vez de APIs. É um pouco subjetivo, mas talvez seja "mais sustentável". Embora seja verdade, eu gosto mais dessa abordagem do que depender de um valor padrão, como sugerem muitas outras respostas.
Nicholas Miller
3

Ele atribuirá o valor de v1a v2se não for nulo, caso contrário, o valor padrão será zero.

v2=v1??0

Ou abaixo é a outra maneira de escrevê-lo.

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

No C # 7.1 e posterior, o tipo pode ser inferido usando o defaultliteral em vez do defaultoperador, para que possa ser escrito da seguinte maneira:

v2 = v1 ?? default;
akesfeden
fonte
-1
 int v2= Int32.Parse(v1.ToString());
mohammad qavizi
fonte
5
Embora esse código possa responder à pergunta, fornecer um contexto adicional a respeito de por que e / ou como esse código responde à pergunta melhora seu valor a longo prazo.
xiawi 10/03
1
É melhor usar a maneira "melhor prática" para desembrulhar opcionais, em vez de usar truques secretos. Consulte docs.microsoft.com/en-us/dotnet/csharp/language-reference/… para obter referência
lorg
Ao responder a uma pergunta de oito anos com quinze respostas existentes, é importante explicar qual é o novo aspecto da pergunta que sua resposta está abordando e observar se a passagem do tempo mudou a resposta. As respostas somente de código quase sempre podem ser aprimoradas com a adição de algumas explicações.
Jason Aller