[.net] FirstOrDefault : null 이외의 기본값

내가 이해하는 것처럼 Linq에서 메소드 FirstOrDefault()Defaultnull 이외 의 값을 반환 할 수 있습니다 . 내가 해결하지 않은 것은 쿼리 결과에 항목이 없을 때 null (이와 비슷한) 메소드로 null 이외의 다른 유형을 반환 할 수 있다는 것입니다. 특정 쿼리에 대한 값이없는 경우 미리 정의 된 일부 값이 기본값으로 반환되도록 설정할 수있는 특정 방법이 있습니까?



답변

값 유형이 아닌 일반적인 경우 :

static class ExtensionsThatWillAppearOnEverything
{
    public static T IfDefaultGiveMe<T>(this T value, T alternate)
    {
        if (value.Equals(default(T))) return alternate;
        return value;
    }
}

var result = query.FirstOrDefault().IfDefaultGiveMe(otherDefaultValue);

다시 말하지만, 시퀀스 어떤 것이 있는지 또는 첫 번째 값이 기본값 인지 알 수 없습니다 .

당신이 이것에 관심이 있다면, 당신은 같은 것을 할 수 있습니다

static class ExtensionsThatWillAppearOnIEnumerables
{
    public static T FirstOr<T>(this IEnumerable<T> source, T alternate)
    {
        foreach(T t in source)
            return t;
        return alternate;
    }
}

로 사용

var result = query.FirstOr(otherDefaultValue);

Steak 씨가 지적했듯이 이것은 이것에 의해서도 가능 .DefaultIfEmpty(...).First()합니다.


답변

내가 이해하는 것처럼 Linq에서 FirstOrDefault () 메소드는 null 이외의 기본값을 반환 할 수 있습니다.

또는 요소 유형의 기본값을 항상 리턴합니다. 이는 널 참조, 널 입력 가능 값 유형의 널 (NULL) 값 또는 널 입력 불가능 값 유형의 자연 “모든 0″값입니다.

특정 쿼리에 대한 값이없는 경우 미리 정의 된 일부 값이 기본값으로 반환되도록 설정할 수있는 특정 방법이 있습니까?

참조 유형의 경우 다음을 사용할 수 있습니다.

var result = query.FirstOrDefault() ?? otherDefaultValue;

물론 첫 번째 값이 존재하지만 null 참조 인 경우 “기타 기본값” 제공합니다 …


답변

DefaultIfEmpty 다음에 First를 사용할 수 있습니다 .

T customDefault = ...;
IEnumerable<T> mySequence = ...;
mySequence.DefaultIfEmpty(customDefault).First();


답변

FirstOrDefault 문서에서

소스가 비어 있으면 [Returns] default (TSource);

default (T)에 대한 문서에서 :

기본 키워드. 참조 유형의 경우 null을, 숫자 값 유형의 경우 0을 반환합니다. 구조체의 경우 구조체의 값 또는 참조 유형에 따라 0 또는 null로 초기화 된 구조체의 각 멤버를 반환합니다. nullable 값 형식의 경우 default는 모든 구조체와 같이 초기화되는 System.Nullable을 반환합니다.

따라서 유형이 참조인지 또는 값 유형인지에 따라 기본값은 null 또는 0 일 수 있지만 기본 동작은 제어 할 수 없습니다.


답변

@sloth의 코멘트에서 복사 함

대신에 예를 들어 YourCollection.FirstOrDefault()사용할 수 있습니다 YourCollection.DefaultIfEmpty(YourDefault).First().

예:

var viewModel = new CustomerDetailsViewModel
    {
            MainResidenceAddressSection = (MainResidenceAddressSection)addresses.DefaultIfEmpty(new MainResidenceAddressSection()).FirstOrDefault( o => o is MainResidenceAddressSection),
            RiskAddressSection = addresses.DefaultIfEmpty(new RiskAddressSection()).FirstOrDefault(o => !(o is MainResidenceAddressSection)),
    };


답변

당신은 또한 이것을 할 수 있습니다

    Band[] objects = { new Band { Name = "Iron Maiden" } };
    first = objects.Where(o => o.Name == "Slayer")
        .DefaultIfEmpty(new Band { Name = "Black Sabbath" })
        .FirstOrDefault();   // returns "Black Sabbath" 

이것은 linq만을 사용합니다-yipee!


답변

실제로 NullReferenceException컬렉션 을 사용할 때 피하기 위해 두 가지 접근 방식을 사용합니다 .

public class Foo
{
    public string Bar{get; set;}
}
void Main()
{
    var list = new List<Foo>();
    //before C# 6.0
    string barCSharp5 = list.DefaultIfEmpty(new Foo()).FirstOrDefault().Bar;
    //C# 6.0 or later
    var barCSharp6 = list.FirstOrDefault()?.Bar;
}

C # 6.0 이상의 경우 :

사용 ?.또는 ?[테스트에 널 (null)이 전 멤버 액세스를 수행하는 경우 널 조건부 연산자 문서

예:
var barCSharp6 = list.FirstOrDefault()?.Bar;

C # 이전 버전 :

DefaultIfEmpty()시퀀스가 비어있는 경우 기본값을 검색하는 데 사용 합니다. MSDN 설명서

예:
string barCSharp5 = list.DefaultIfEmpty(new Foo()).FirstOrDefault().Bar;