Por que chamar algumas funções da classe de objeto, em uma instância do tipo primitivo, precisa de boxe?
-
24-09-2019 - |
Pergunta
Descobri que, se eu executar as seguintes linhas de código.
int i = 7;
i.GetHashCode(); //where GetHashCode() is the derived
//function from System.Object
Nenhum boxe está pronto, mas se eu ligar i.GetType()
(outra função derivada de System.Object
) no lugar de GetHashCode()
, um boxe será obrigado a ligar GetType()
, Por que não é possível ligar GetType()
na instância do tipo primitivo diretamente, sem boxe, enquanto é possível ligar GetHashCode()
sem boxe?
Solução
A chave aqui é que GetType()
não é virtual e não pode ser substituído. Uma vez que uma estrutura é efetivamente sealed
, os métodos não podem ser substituídos mais do que a estrutura, portanto o tempo de execução e o compilador podem tratar os métodos da estrutura que foram substituídos como chamadas estáticas.
Se você escreve uma estrutura (rara) você deve substituir todos os métodos como ToString()
, Equals()
, GetHashCode()
por exatamente esse motivo. Se não o fizer, ele deve caixa. No entanto, GetType()
não podes ser substituído, portanto, precisa de boxe.
Isso realmente leva a algumas casas de borda estranhas com Nullable<T>
e boxe, desde um vazio Nullable<T>
caixas para null
, assim:
int i = obj.GetHashCode(); // fine
Type t = obj.GetType(); // boom
Outras dicas
Eu acho que o motivo é que o GethashCode é implementado no System.int32 diretamente, você chama System.int32 :: gethashcode (). Não há necessidade de caixa se você chamar uma função de membro conhecida em um tipo de valor.
Parece muito próximo de Como o valuetype.getType () é capaz de determinar o tipo de estrutura?
Também relacionado está GetType e tipoof confusão