Pelo que entendi, no Linq o método FirstOrDefault()
pode retornar um Default
valor de algo diferente de nulo. O que ainda não descobri é que tipo de coisa diferente de nulo pode ser retornada por esse método (e semelhante) quando não há itens no resultado da consulta. Existe alguma maneira específica de configurar isso para que, se não houver valor para uma consulta específica, algum valor predefinido seja retornado como o valor padrão?
142
YourCollection.FirstOrDefault()
, você poderia usarYourCollection.DefaultIfEmpty(YourDefault).First()
por exemplo.MyCollection.Last().GetValueOrDefault(0)
para isso. Caso contrário, a resposta de @Jon Skeet abaixo está correta na IMO.Respostas:
Caso geral, não apenas para tipos de valor:
Novamente, isto não pode realmente dizer se há foi nada na sua sequência, ou se o primeiro valor era o padrão.
Se você se importa com isso, pode fazer algo como
e use como
embora, como o Sr. Steak ressalte, isso poderia ser feito da mesma maneira
.DefaultIfEmpty(...).First()
.fonte
<T>
em seus nomes, mas mais grave é quevalue == default(T)
não funciona (porque quem sabe seT
pode ser comparado por igualdade?)EqualityComparer<T>.Default.Equals(value, default(T))
para evitar o boxe e evitar uma exceção se o valor énull
Não. Ou melhor, ele sempre retorna o valor padrão para o tipo de elemento ... que é uma referência nula, o valor nulo de um tipo de valor nulo ou o valor natural "todos os zeros" para um tipo de valor não nulo.
Para tipos de referência, você pode apenas usar:
Obviamente, isso também fornecerá o "outro valor padrão" se o primeiro valor estiver presente, mas for uma referência nula ...
fonte
int
. Eu prefiro muito mais o uso deDefaultIfEmpty
:src.Where(filter).DefaultIfEmpty(defaultValue).First()
. Funciona para o tipo de valor e o tipo de referência.Você pode usar DefaultIfEmpty seguido por First :
fonte
DefaultIfEmpty
- ele funciona com todas as APIs que precisam de um padrão a ser especificado:First()
,Last()
, etc. Como usuário, você não precisa se lembrar que APIs permitem especificar padrão que não fazer. Muito elegante!A partir da documentação para FirstOrDefault
Na documentação para o padrão (T) :
Portanto, o valor padrão pode ser nulo ou 0, dependendo se o tipo é uma referência ou um tipo de valor, mas você não pode controlar o comportamento padrão.
fonte
Copiado do comentário por @sloth
Em vez de
YourCollection.FirstOrDefault()
, você poderia usarYourCollection.DefaultIfEmpty(YourDefault).First()
por exemplo.Exemplo:
fonte
DefaultIfEmpty
retorna o padrão SE a coleção estiver vazia (possui 0 itens). Se você usarFirst
WITH uma expressão correspondente, como no seu exemplo, e essa condição não encontrar nenhum item, seu valor de retorno estará vazio.Você também pode fazer isso
Isso usa apenas linq - yipee!
fonte
FirstOrDefault
vez deFirst
. De acordo com msdn.microsoft.com/en-us/library/bb340482.aspx , o uso recomendado éFirst
Na verdade, uso duas abordagens para evitar
NullReferenceException
quando estou trabalhando com coleções:Para C # 6.0 ou posterior:
Use
?.
ou?[
para testar se é nulo antes de executar uma documentação de Operadores com Condição Nula de Acesso de MembroExemplo:
var barCSharp6 = list.FirstOrDefault()?.Bar;
C # versão mais antiga:
Use
DefaultIfEmpty()
para recuperar um valor padrão se a sequência estiver vazia. Documentação MSDNExemplo:
string barCSharp5 = list.DefaultIfEmpty(new Foo()).FirstOrDefault().Bar;
fonte
Em vez de
YourCollection.FirstOrDefault()
, você poderia usarYourCollection.DefaultIfEmpty(YourDefault).First()
por exemplo.fonte
Eu apenas tive uma situação semelhante e estava procurando uma solução que me permitisse retornar um valor padrão alternativo sem cuidar dele no lado do chamador toda vez que eu precisar. O que geralmente fazemos no caso do Linq não suportar o que queremos é escrever uma nova extensão que cuide disso. Isso é o que eu fiz. Aqui está o que eu vim com (ainda não testado):
fonte
Eu sei que já faz um tempo, mas vou acrescentar a isso, com base na resposta mais popular, mas com uma pequena extensão, gostaria de compartilhar o seguinte:
Isso me permite chamá-lo em linha, como tal, com meu próprio exemplo, que estava tendo problemas com:
Então, para mim, eu só queria que um resolvedor padrão fosse usado em linha, posso fazer minha verificação usual e passar uma função para que uma classe não seja instanciada, mesmo que não seja usada, é uma função a ser executada quando necessário!
fonte
Use em
DefaultIfEmpty()
vez deFirstOrDefault()
.fonte