Não é possível converter tipo 'string' para 'int?' através de uma conversão de referência, a conversão de boxe, a conversão unboxing, conversão de acondicionamento ou de conversão do tipo nulo

StackOverflow https://stackoverflow.com/questions/887943

  •  23-08-2019
  •  | 
  •  

Pergunta

C # aceita o seguinte:

object o = "hello";
int? i = o as int?;

if (i == null) {
    // o was not a boxed int
}
else {
    // Can use i.Value to recover the original boxed value
}

Mas não

String o = "hello";
int? i = o as int?;

if (i == null) {
    // o was not a boxed int
}
else {
    // Can use i.Value to recover the original boxed value
}

Eu estou apenas perguntando sobre o comportamento da palavra-chave as em C #.

O mesmo que em Java isso iria falhar:

Object test1 = "hello";
Integer test2 = (Integer) test1;
String test3 = "hello";
Integer test4 = (Integer) test3; //compilation error
Foi útil?

Solução

O compilador sabe que uma corda nunca pode ser uma int? por isso diz-lhe isso. Isso não significa que int? não é útil. Seu caso de uso tentativa está longe de ser a única normal. O normal é "Eu quero representar um inteiro e a possibilidade de que o valor está faltando / desconhecido". Para isso, int? funciona muito bem.

Por que você esperar seu código original para o trabalho? Por que seria útil?

Note que você pode uso as com tipos anuláveis, para unboxing:

object o = "hello";
int? i = o as int?;

if (i == null)
{
    // o was not a boxed int
}
else
{
    // Can use i.Value to recover the original boxed value
}

EDIT: Depois de ter visto o seu comentário, você não usar as às coisas de análise. Você provavelmente vai querer usar int.TryParse :

string text = "123":
int value;
if (int.TryParse(text, out value))
{
    Console.WriteLine("Parsed successfully: {0}", value);
}
else
{
    Console.WriteLine("Unable to parse text as an integer");
}

Se você tem certeza a string é feito para ser um inteiro (ou seja, é um bug de outra forma), então você pode simplesmente usar int.Parse :

int value = int.Parse(text);

Isso vai lançar uma exceção se a análise falhar.

Note também que ambos os métodos permite que você especifique um provedor de formato (geralmente uma informação de cultura) que lhe permite expressar como os números são expressos nesse formato (por exemplo, milhares separadores).

EDIT: Em resposta à sua nova pergunta, o compilador impede que isso porque sabe uma string não pode possivelmente ser um int em caixa - a conversão nunca vai ter sucesso. Quando se sabe apenas que o valor original é um objeto, ele pode ter sucesso.

Por exemplo, suponha que eu lhe disse: "Aqui está uma forma: é um quadrado?" Essa é uma pergunta sensata. É razoável perguntar isso:. Você não pode dizer sem olhar para a forma

Se, no entanto, eu disse: "Aqui está um triângulo:? É um quadrado" Então você estaria razoavelmente direito a rir na minha cara, como um triângulo não pode ser um quadrado -. A pergunta não faz sentido

Outras dicas

int? significa um tipo inteiro nulo, e não um int que pode conter qualquer outro tipo de variável.

Se você quiser um tipo de variável que pode conter um int ou uma string, você teria que usar um objeto, ou uma string suponho, e depois viver uma vida cheia com o tipo de fundição. Eu não sei por que você iria querer fazer isso, no entanto.

int? permite armazenar qualquer valor inteiro, ou um valor nulo. Que é útil quando dizem que a resposta para a pergunta "Quantos pedidos tem essa pessoa colocada" é legitimamente "Eu não sei" em vez de uma série de ordens, ou zero, o que seria "Eu sei para um fato esta pessoa nunca tem colocado um fim".

Eu quero adicionar um pouco mais informações.

Um outro caso, porque o elenco é inválido e o compilador gera um erro na compilação é que System.String é marcado como selada . Assim, o compilador sabe de quais tipos de System.String inherites e quais os tipos que você pode lançar a string usando o como -Operador.

Devido à palavra-chave selada , o compilador também sabe que você não pode herdar de System.String para adicionar funcionalidade ou implementar algumas interfaces adicionais .

O código abaixo é um exemplo e o compilador irá lançar o seguinte erro na compilação

Não é possível converter tipo 'SealedClass' para 'ICastToInterface' através de uma referência conversão, conversão de boxe, conversão unboxing, envolvimento conversão, ou tipo nulo conversão

public class UnsealedClass {
  // some code
}

public sealed class SealedClass {
  // some code
}

public interface ICastToInterface {
  // some code
}

public class Test {

  public Test() {
    UnsealedClass unsealedClass = new UnsealedClass();

    SealedClass sealedClass = new SealedClass();

    ICastToInterface unsealedCast = unsealedClass as ICastToInterface;  // This works fine

    ICastToInterface sealedCast = sealedClass as ICastToInterface; // This won´t compile, cause SealedClass is sealed
  }
}

mas você pode verificar o valor nulo e defini-lo como nulo.

int? blah;
if (blah == null)
{}

int? É um número inteiro anulável, não tem nada a ver com a fundição e o como palavra-chave. "Cordas" é um tipo de cadeia objeto, o que não é convertível em um int (nulo ou não nulo).

A palavra chave é praticamente o mesmo que lançar usando suportes, exceto ele não retornará um erro, ele irá definir o objeto para nulo:

int i = 1;

object o = i; //boxing

int j = (int)o; //unboxing

Este primeiro exemplo funciona como o objeto designado para o representar um int.

Agora, considere:

string i = "MyString";

object o = MyString;

 int j = (int)o //unboxing raises exception

 int j = o as int; //raises compilation Error as int is not nullable
 int? j = o as int?; /// o == null

Espero que isso ajuda a explicar a diferença entre os dois conceitos.

Richard

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top