2012-12-06 120 views
4

我有兩個元素的集合。我試圖在第一個集合中獲取第二個集合中具有匹配ID的所有元素,並針對匹配的元素運行CopyToDomain方法。有沒有更清晰簡潔的方式來表達更好的LINQ語句?

下面的代碼工作正常,但我有點驚訝其冗長。 ReSharper在這裏沒有推薦任何東西,但我想知道是否將兩個集合相交,然後將這個方法映射到元素上會更清楚?你會做出這樣的改變嗎,還是應該停下來大驚小怪,並保持原樣?

Task task = new Task(); 
IList<TaskAttributeDto> taskAttributeDtos = new List<TaskAttributeDto>(); 
taskAttributeDtos.Add(new TaskAttributeDto{ ID = 1}); 
taskAttributeDtos.Add(new TaskAttributeDto{ ID = 2}); 

foreach (TaskAttributeDto taskAttributeDto in taskAttributeDtos) 
{ 
    TaskAttribute matching = task.TaskAttributes.FirstOrDefault(t => t.ID == taskAttributeDto.ID); 
    if (matching != null) 
    { 
     taskAttributeDto.CopyToDomain(matching); 
    } 
} 
+0

您可能有拼寫錯誤,其中'task'定義在哪裏? –

+0

對不起,這只是一小段代碼。如果它相關,我可以提供整個事物,但它只是一個傳入方法的對象。 –

+0

「清晰簡潔」非常含糊而主觀。我認爲你的原始代碼很簡單明瞭,而這些LINQ答案很難閱讀。但那只是我的個人意見;沒有真正正確的答案。 – nateirvin

回答

11

你在做什麼基本上是一個連接,所以你可以使用LINQ的聯接語法:

var matches = 
    from dto in taskAttributesDtos 
    join attribute in task.TaskAttributes on dto.ID equals attribute.ID 
    select new { dto, attribute}; 

foreach (var m in matches) 
    m.dto.CopyToDomain(m.attribute); 
+0

你更喜歡在我的原始代碼中看到這個代碼嗎?我將是第一個承認我不熟悉LINQ表達式查詢的人。 –

+1

這段代碼很好地分離了抽象層次(也是我認爲linq非常重要的原因),而原始代碼通過選擇要在多個位置處理的項目來混合抽象層次。通過將第一個linq語句提取到一個命名好的函數中,即使這個代碼可以變得更好一些。 –

+0

@SeanAnderson,我想我會更喜歡我的,但我想這是個人偏好和習慣的問題......我認爲Linq查詢語法在這種情況下更具有表現力,但如果您願意,不要強迫自己不舒服。最好的代碼通常是您可以輕鬆理解的代碼。 –

1
task.TaskAttributes.Where(t => taskAttributeDtos.Select(d => d.ID).Contains(t.ID)) 
    .ToList() 
    .ForEach(t => taskAttributeDtos.First(d => d.ID == t.ID).CopyToDomain(t)); 
+2

這種方法效率低下,你在搜索DTO兩次 –

2
foreach(TaskAttributeDto taskAttributeDto in taskAttributeDtos.Where(t1 => TaskAttributes .Any(t2 => t2.Id == t1.Id))) 
{ 
    taskAttributeDto.CopyToDomain(taskAttributeDto); 
} 
2

如果你關心查詢語法的可讀性,您可以嘗試使用方法語法:

var matches = taskAttributesDtos.Join(task.TaskAttributes, 
             a => a.ID, 
             b => b.ID, 
             (a, b) => new { dto = a, attribute = b }); 

foreach (var m in matches) 
    m.dto.CopyToDomain(m.attribute); 
0

ori黃金代碼找到第一個匹配項。聯合查找所有匹配項,並且組聯接允許您從每個匹配組中選出一個贏家。

var matches = 
    from dto in taskAttributesDtos 
    join attribute in task.TaskAttributes 
     on dto.ID equals attribute.ID 
     into attributeGroup //into clause causes GroupJoin to be called. 
    select new { dto, attribute = attributeGroup.First() }; 

foreach (var m in matches) 
    m.dto.CopyToDomain(m.attribute); 
相關問題