하나의 항목을 선택하는 Linq 코드


105

일치하는 항목을 하나 선택하기 위해 이와 같은 코드를 많이 작성하고 있습니다.

var item = (from x in Items where x.Id == 123 select x).First();

더 깨끗한 방법이 있습니까, 아니면 제가 얻을 수있는 것처럼 간결합니까?

편집 : "linq 구문을 사용하는 더 깨끗한 방법"이라고 말해야합니다. 나는 이미 람다 구문을 알고 있었고 이것이 실제로 유일한 방법 인 것처럼 보이기 시작했습니다. 그래도 유용한 정보를 얻었으므로 답장 한 모든 사람에게 감사드립니다.


5
개인적으로 나는 피 Single()SingleOrDefault()내가 알고있는 경우 데이터가 있기 때문에 (즉, 제약 조건이 데이터베이스 등에서 예를 들어) 이미 고유 Single()이 가능한 중복을 찾기 위해 목록의 나머지 부분을 스캔하는 힘,하지만 저예요. 이 시점에서 고유성을 적용해야하는 경우 Single()가족을 사용 하고 그렇지 않은 경우 First()가족을 사용 합니다.
James Michael Hare

답변:


176

linq 쿼리 구문이 얼마나 마음에 드는지에 따라 다음과 같은 확장 메서드를 직접 사용할 수 있습니다.

var item = Items.First(i => i.Id == 123);

목록이 비어있는 경우 오류가 발생하지 않도록 FirstOrDefault하려면 요소 유형 ( null참조 유형의 경우)에 대한 기본값을 반환하는 값을 사용하세요 .

var item = Items.FirstOrDefault(i => i.Id == 123);

if (item != null)
{
    // found it
}

Single()그리고 SingleOrDefault()도 사용할 수 있지만, 데이터베이스 또는 무언가에서 읽고 있다면 이미 보장 거기 어떤 중복이고 던져 있는지 목록을 검색하는 나는 귀찮게하지 않을 고유성 것을 할 수 있습니다. First()FirstOrDefault() 그들은 더 효율적입니다, 그래서 첫 경기에 중지합니다.

First()Single()가족 중 그들이 던지는 곳 은 다음 과 같습니다.

  • First() -비어 있거나 찾을 수없는 경우 던지고, 중복되는 경우 던지지 않습니다.
  • FirstOrDefault() -비어 있거나 찾을 수없는 경우 기본값을 반환하고 중복 된 경우 throw하지 않습니다.
  • Single() -비어 있거나 찾을 수 없으면 던지고, 중복이 있으면 던집니다.
  • SingleOrDefault() -비어 있거나 찾을 수없는 경우 기본값을 반환하고 중복이 있으면 발생합니다.

1
나는 당신이 두 개의 등호를 놓치고 있다고 생각합니다. 되어야합니다i.Id == 123
davehale23

18

시나리오 및 0 개 이상의 일치 항목을 처리할지 여부에 따라 FirstOrDefault 또는 SingleOrDefault 가 유용 할 수 있습니다.

FirstOrDefault : 시퀀스의 첫 번째 요소를 반환하거나 요소가없는 경우 기본값을 반환합니다.

SingleOrDefault : 시퀀스의 유일한 요소 또는 시퀀스가 ​​비어있는 경우 기본값을 반환합니다. 이 메서드는 시퀀스에 둘 이상의 요소가있는 경우 예외를 throw합니다.

나는 이것이 linq 'from'쿼리에서 어떻게 작동하는지 모르지만 람다 구문에서는 다음과 같이 보입니다.

var item1 = Items.FirstOrDefault(x => x.Id == 123);
var item2 = Items.SingleOrDefault(x => x.Id == 123);

DB 시간 측면에서 가장 효율적인 것은 무엇입니까? 내가 varchar를 가지고 있다면 정확한 일치를 원했지만 가능하지 않을 수 있습니까?
Piotr Kula 2013

2
허용되는 답변은이 문제를 완전히 해결하지만 기본적으로 FirstOrDefault는 일치 항목을 찾는 즉시 중지되지만 SingleOrDefault는 전체 목록을 검사하여 정확히 하나의 일치 항목 이 있는지 확인해야합니다 .
stuartd

12

다음은 선호되는 방법입니다.

var item = Items.SingleOrDefault(x => x.Id == 123);

또는

var item = Items.Single(x => x.Id == 123);

감사합니다.이 상황에서는 linq 표기법이없고 람다를 사용해야합니까?
Mikey Hogarth 2011 년

꽤 좋습니다. 실제로 linq를 많이 사용하지 않았기 때문에 이러한 방법을 알고 있는지도 잘 모르겠습니다.
wageoghe

1
단일 메서드는 반환 값이 고유한지 확인합니다. 따라서 컬렉션이 크면 많은 시간이 걸릴 수 있습니다. 첫 번째 메소드는 술어와 일치하는 첫 번째 요소를 리턴합니다.
meziantou

@wageoghe James의 대답은 linq를 사용하지 않습니다. Single 및 SingleOrDefault 메서드는 IEnumerable 구현의 일부입니다.
Mikey Hogarth

12

누군가의 삶을 더 쉽게 만들기 위해 람다 표현식을 사용한 linq 쿼리

(from x in Items where x.Id == 123 select x).FirstOrDefault();

SQL 쿼리가 발생합니까? select top (1) 합니다.


9

그것은 이것으로 더 잘 압축 될 수 있습니다.

var item = Items.First(x => x.Id == 123);

귀하의 질의는 현재 모든 결과를 수집 (그리고 하나 이상이있을 수 있음) 열거 내의 다음의 첫 번째 복용 이를 집합 필요한 것보다 더 많은 작업을 수행합니다.

Single / SingleOrDefault는 가치가 있지만 전체 컬렉션을 반복하고 해당 일치를 선택하는 것 외에도 일치가 고유한지 확인하려는 경우에만 해당됩니다. First / FirstOrDefault는 실제로 얼마나 많은 중복 항목이 있는지에 관계없이 첫 번째 일치 항목을 선택하고 종료합니다.


4

확장 메서드 구문을 사용할 수 있습니다.

var item = Items.Select(x => x.Id == 123).FirstOrDefault();

그 외에는 자신 만의 특별한 "First"및 "FirstOrDefault"확장 메서드를 작성하지 않고도 얼마나 더 간결하게 할 수 있는지 잘 모르겠습니다.


나는 이것이 의도 된 행동이라고 생각하지 않습니다. 이 Select 명령어는 항목의 각 요소에 대해 하나씩 bool 컬렉션을 반환합니다 (실제로 반환을 위해 선택 함). 항목으로 반환되는 첫 번째 항목은 단순히 bool이됩니다. 크리스 Hannon의 솔루션을 사용
레오나르도 Daga

이미 언급 된 Where과 반대를 의미 할 수도 Select있지만이 대답은 올바르지 않습니다. C #에서 Select는 결과를 IEnumerable <bool>로 변경하므로 bool첫 번째 항목에 대한 결과가 표시됩니다.x.Id == 123
bradlis7

2

무엇이 저에게 효과적 이었는지 말씀 드리겠습니다.

int id = int.Parse(insertItem.OwnerTableView.DataKeyValues[insertItem.ItemIndex]["id_usuario"].ToString());

var query = user.First(x => x.id_usuario == id);
tbUsername.Text = query.username;
tbEmail.Text = query.email;
tbPassword.Text = query.password;

내 ID는 쿼리하려는 행입니다.이 경우 radGrid에서 가져온 다음 쿼리에 사용했지만이 쿼리는 행을 반환 한 다음 쿼리에서 얻은 값을 텍스트 상자 또는 기타 항목에 할당 할 수 있습니다. , 나는 그것들을 텍스트 상자에 할당해야했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.