Pergunta

Considere o seguinte::

Object box = 5;
int @int = (int)box;  // int = 5
int? nullableInt = box as int?; // nullableInt = 5;
StringComparison @enum = (StringComparison)box; // enum = OrdinalIgnoreCase
StringComparison? nullableEnum = box as StringComparison?; // nullableEnum = null.

2 coisas ::

  1. Por que posso desbotar para StringComparison? Eu acho que isso é porque o tipo subjacente é Int32 Mas ainda acho estranho.
  2. Porque nullableEnum tem um valor de nulo?

Pelo que entendi, o único unboxing válido é de um tipo de valor em caixa é para o tipo ou para um tipo anulável. Se int pode unbox para Enum, então por que o mesmo vale para os valores anuláveis? Da mesma forma, se, em vez de 5, eu encaixei StringComparison.OrdinalIgnoreCase, seria isso nullableInt seria nulo, mas nullableEnum não seria.

Foi útil?

Solução

Estritamente falando, eu acho que é um Bug in Detalhe de implementação de O tempo de execução, desde a especificação C# diz

A unidade para um tipo anulável produz o valor nulo do tipo anulável se o operando de origem for nulo ou o resultado embrulhado de desbotar a instância do objeto para o tipo subjacente do tipo anulado de outra forma.

Isto é, se unirboxing para StringComparison funciona, então desbota -se para Nullableu003CStringComparison> deve funcionar também. Não está claro se os dois devem funcionar ou ambos falharem. A especificação diz que

Para uma conversão de unboxing para um determinado tipo de valor não nulo para ter sucesso em tempo de execução, o valor do operando de origem deve ser uma referência a um valor em caixa desse tipo de valor não indicado.

Você deve decidir se um INT em caixa é considerado um valor em caixa do tipo StringComparison, porque o tipo subjacente de StringComparison é int. A especificação continua dizendo que um invalidcastException é jogado se a caixa contiver um "objeto incompatível". Um INT é certamente "compatível" com a StringComparison, porque você pode copiar com segurança os quatro bytes da pilha na sua variável StringComparison.

Outras dicas

Quando você lança enum ou número inteiro para se opor, ele ainda mantém informações de tipo. Então box is StringComparison retornará false. Mas é permitido lançar qualquer enumeração ou int a qualquer enumeração, tão explícito (StringComparison)box funciona. É um caso especial para enumes. Nullable<T>, por outro lado, é apenas uma aula usual, T não é tratada de maneira específica quando você lança ou verifica o tipo. É por isso que esse código lançará exceção.

        StringComparison? nullableEnum = (StringComparison?)nullableInt;

1) Sim, o tipo de enum subjacente é int e é por isso que funciona dessa maneira. Ainda mais. Você pode fazer o seguinte:

enum MyEnum
{
    One = 1,
    Two = 2,
}

int i = 3;
MyEnum myEnum = (MyEnum)i; // This works without exceptions.

2) porque StringComparison? é na verdade Nullable<StringComparison> que é tipo diferente. E as O operador verifica apenas se o objeto é do mesmo tipo especificado no operador.

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