CLR: Se um construtor não será sempre lançar uma exceção?
-
20-08-2019 - |
Pergunta
Em Delphi, se houvesse uma exceção durante a construção de um objeto: qualquer memória alocada seria lançado e uma exceção será lançada. Por exemplo, o seguinte foi garantida para retornar um válido Camera
objeto, ou lançar uma exceção:
Camera c = new Camera();
Você não tinha que verificar a variável resultante para nulo:
Camera c = new Camera();
if (c == null)
throw new Exception("Error constructing Camera") //waste of time
É a mesma verdade no CLR?
E existem outras constucts syntatical onde um valor de retorno é garantido para qualquer ser válido, ou lançar uma exceção?
- A criação de estruturas (por exemplo retângulo)?
- recebendo um membro de uma enumeração?
- o resultado de Object.ToString ()?
- operações mathmatical?
No caso de matemática desempenho:
Int32 aspect = 1650.0 / 1080.0;
if (aspect == null)
throw new Exception("Division of two numbers returned null")
Solução
Um construtor em .Net é garantida para retornar uma instância não-nula do tipo do objeto. Quer ou não a instância é válido depende a semântica individuais do tipo.
Exceções lançadas em um construtor não será arbitrariamente engolido pelo CLR (embora o código do usuário pode engoli-los). O CLR irá propagar uma exceção apenas como exceções lançadas em qualquer outro método e os objetos acabará por ser adequadamente lixo coletado.
Quanto aos outros casos que você mencionou
- A criação de estruturas: Estruturas, por definição, não pode nunca ser nulo. Exceções lançadas no construtor irá propagar normalmente
- Conseguir um membro de uma enumeração: Enumerations são strutures / tipos de valor sob o capô e também nunca vai ser nulo
- o resultado de Object.ToString (): Isso pode (e, infelizmente, vai) ser nulo. String é um tipo de referência e é perfeitamente legal para retornar nulo de uma substituição de ToString (por favor, não).
- As operações matemáticas: Isso depende fortemente de ambos a configuração estouro do seu projeto e do tipo particular sendo usado (integral ponto vs. flutuante).
A questão matemática quase merece uma resposta sobre o seu próprio. Por um lado o resultado de uma operação matemática em tipos primitivos nunca vai ser nulo. Mas ele ainda pode ser inválido. Por exemplo, o código a seguir não vai jogar, mas se o resultado é válido depende muito da sua situação específica
float f1 = 1.0;
float f2 = f1 / 0;
Neste ponto F2 é um valor flutuante muito específico que não representa um número real. É válido? Depende do seu caso de uso.
Outras dicas
Sim. Eu gostaria de colocar desta forma (como falha pode significar falha lógica também): Se um construtor não lançar uma exceção, o valor de retorno é garantido para ser não null
para que você nunca tem que executar essa verificação.
Criação de estruturas (por exemplo retangular): Um struct
não pode ser de todo null
(tipos Nullable
são considerados completamente tipos diferentes, isto é typeof(int?) != typeof(int)
). Chamar um construtor de uma estrutura seria ou falhar por lançar uma exceção ou retornar uma instância.
Conseguir um membro de uma enumeração: Um enum
é um apenas um conjunto de constantes. Não há nada como "ficando um membro em tempo de execução." É substituído em tempo de compilação.
O resultado da Object.ToString()
:. Como qualquer método, ele pode retornar qualquer valor válido para o tipo string
que inclui null
e também pode lançar uma exceção (nesse caso, ele não retorna um valor em tudo)
As operações matemáticas: Todas as expressões irá retornar um valor ou lançar uma exceção. O valor de retorno pode ser qualquer valor válido para esse tipo (por exemplo Int32
nunca pode ser null
).