Entendendo melhor a diferença entre as formas de obtermos informações de um objeto do tipo Entity. Na imagem abaixo, são apresentadas duas formas de obtermos o valor do campo firstname da entidade contato.
Em determinados cenários, o resultado final de ambas será igual, por exemplo, em um create/update onde este campo este foi preenchido e vira preenchido dentro do target. Porém, em determinadas situações, como em um update, onde o campo firstname não foi atualizado, a primeira linha irá gerar uma exceção, pois o objeto contato não possuirá este atributo. Caso estejamos fazendo o uso do método GetAttributeValue<T>("attributeLogicalName"), juntamente com um atributo cujo tipo e nullable, o retorno será null e nenhuma exceção será gerada.
E quando estivermos trabalhando com tipos de atributos non-nullable, como DateTime, int, bool, entre outros? Nestes casos, o próprio método se encarrega de fazer uma tratativa. A primeira linha abaixo é a minha chamada, a segunda linha, é o que de fato (implicitamente) será executado.
O método GetValueOrDefault(), como o próprio nome já diz, retorna o valor do campo e, quando não encontrado, retorna o valor padrão para aquele tipo de atributo.
Um último ponto a ser explorado no método GetValueOrDefault() é referenete a sua sobrecarga, onde você pode passar um valor padrao para sua variável. Continuando o exemplo com o tipo DateTime que se encaixa bem neste cenário. O valor default para data é 01/01/0001. Esta não é uma data válida para as tabelas do CRM. Sabendo disso, poderíamos fazer a tratativa de duas formas.
Primeiramente, usando uma condição para setar um valor padrão para data, caso o valor retornado seja igual a MinValue.
Ou, podemos usar sua sobrecarga e passarmos um valor padrão que, além de evitarmos exceções, diminuem a quantidade de linhas de código.