FirstOrDefault : null 이외의 기본값
내가 이해하는 것처럼 Linq에서 메소드 FirstOrDefault()
는 Default
null 이외 의 값을 반환 할 수 있습니다 . 내가 해결하지 않은 것은 쿼리 결과에 항목이 없을 때 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 이외의 기본값을 반환 할 수 있습니다.
또는 요소 유형의 기본값을 항상 리턴합니다. 이는 널 참조, 널 입력 가능 값 유형의 널 값 또는 널 입력 불가능 값 유형의 자연 "모든 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!
Actually, I use two approaches to avoid NullReferenceException
when I'm working with collections:
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;
}
For C# 6.0 or later:
Use ?.
or ?[
to test if is null before perform a member access Null-conditional Operators documentation
Example: var barCSharp6 = list.FirstOrDefault()?.Bar;
C# older version:
Use DefaultIfEmpty()
to retrieve a default value if the sequence is empty.MSDN Documentation
Example: string barCSharp5 = list.DefaultIfEmpty(new Foo()).FirstOrDefault().Bar;
I just had a similar situation and was looking for a solution that allows me to return an alternative default value without taking care of it at the caller side every time I need it. What we usually do in case Linq does not support what we want, is to write a new extension that takes care of it. That´s what I did. Here is what I came up with (not tested though):
public static class EnumerableExtensions
{
public static T FirstOrDefault<T>(this IEnumerable<T> items, T defaultValue)
{
foreach (var item in items)
{
return item;
}
return defaultValue;
}
public static T FirstOrDefault<T>(this IEnumerable<T> items, Func<T, bool> predicate, T defaultValue)
{
return items.Where(predicate).FirstOrDefault(defaultValue);
}
public static T LastOrDefault<T>(this IEnumerable<T> items, T defaultValue)
{
return items.Reverse().FirstOrDefault(defaultValue);
}
public static T LastOrDefault<T>(this IEnumerable<T> items, Func<T, bool> predicate, T defaultValue)
{
return items.Where(predicate).LastOrDefault(defaultValue);
}
}
Instead of YourCollection.FirstOrDefault()
, you could use YourCollection.DefaultIfEmpty(YourDefault).First()
for example.
I know its been a while but Ill add to this, based on the most popular answer but with a little extension Id like to share the below:
static class ExtensionsThatWillAppearOnIEnumerables
{
public static T FirstOr<T>(this IEnumerable<T> source, Func<T, bool> predicate, Func<T> alternate)
{
var thing = source.FirstOrDefault(predicate);
if (thing != null)
return thing;
return alternate();
}
}
This allows me to call it inline as such with my own example I was having issues with:
_controlDataResolvers.FirstOr(x => x.AppliesTo(item.Key), () => newDefaultResolver()).GetDataAsync(conn, item.ToList())
So for me I just wanted a default resolver to be used inline, I can do my usual check and then pass in a function so a class isn't instantiated even if unused, its a function to execute when required instead!
Use DefaultIfEmpty()
instead of FirstOrDefault()
.
참고URL : https://stackoverflow.com/questions/12972295/firstordefault-default-value-other-than-null
'IT story' 카테고리의 다른 글
각 경로 및 컨트롤러에서 AngularJS- 로그인 및 인증 (0) | 2020.07.02 |
---|---|
angular2에서 ng-disabled에 대한 대안이 있습니까? (0) | 2020.07.02 |
Objective-C에서와 같은 방식으로 Swift에 속성을 저장하는 방법은 무엇입니까? (0) | 2020.07.02 |
SQL Server 문자열 또는 이진 데이터가 잘립니다 (0) | 2020.07.02 |
자바 스크립트가 배열되어 있습니다 (0) | 2020.07.02 |