이것은 LINQ를 사용하여 발을 적시는 사람들에게 알려진 함정입니다.
public class Program
{
public static void Main()
{
IEnumerable<Record> originalCollection = GenerateRecords(new[] {"Jesse"});
var newCollection = new List<Record>(originalCollection);
Console.WriteLine(ContainTheSameSingleObject(originalCollection, newCollection));
}
private static IEnumerable<Record> GenerateRecords(string[] listOfNames)
{
return listOfNames.Select(x => new Record(Guid.NewGuid(), x));
}
private static bool ContainTheSameSingleObject(IEnumerable<Record>
originalCollection, List<Record> newCollection)
{
return originalCollection.Count() == 1 && newCollection.Count() == 1 &&
originalCollection.Single().Id == newCollection.Single().Id;
}
private class Record
{
public Guid Id { get; }
public string SomeValue { get; }
public Record(Guid id, string someValue)
{
Id = id;
SomeValue = someValue;
}
}
}
원본 컬렉션을 만들기 위해 제공된 각 이름에 대해 select 함수가 계속 재평가되고 결과 Record
개체가 새로 만들어 지기 때문에 "False"가 인쇄 됩니다. 이 문제를 해결하기 위해 ToList
의 끝에 간단한 호출을 추가 할 수 있습니다 GenerateRecords
.
이런 식으로 구현함으로써 Microsoft는 어떤 이점을 얻었습니까?
구현이 단순히 결과를 내부 배열로 캐시하지 않는 이유는 무엇입니까? 발생하는 일 중 하나의 특정 부분 은 실행 지연 일 수 있지만이 동작 없이는 여전히 구현 될 수 있습니다.
LINQ가 반환 한 컬렉션의 특정 멤버가 평가되면 내부 참조 / 복사를 유지하지 않고 대신 기본 결과로 동일한 결과를 다시 계산하면 어떤 이점이 있습니까?
반복해서 재 계산 된 동일한 컬렉션 멤버에 대한 논리에 특별한 요구가있는 경우, 선택적 매개 변수를 통해 지정할 수 있고 기본 동작은 그렇지 않은 것으로 보입니다. 또한 지연된 실행으로 얻을 수있는 속도 이점은 궁극적으로 동일한 결과를 지속적으로 다시 계산하는 데 걸리는 시간에 비해 줄어 듭니다. 마지막으로 이것은 LINQ를 처음 사용하는 사람들에게는 혼란스러운 블록이며 궁극적으로 모든 사람의 프로그램에서 미묘한 버그로 이어질 수 있습니다.
이 점에서 어떤 이점이 있으며, Microsoft가이 계획을 매우 신중하게 결정한 이유는 무엇입니까?
return listOfNames.Select(x => new Record(Guid.NewGuid(), x)).ToList();
"캐시 된 사본"을 제공합니다. 문제 해결됨.