2013-08-12 2 views
0
dt = ds.Tables[1]; 

foreach (EPSFromElement element in elementList) 
{ 
    foreach (DataRow row in dt.Rows) 
    { 
     foreach (DataColumn column in dt.Columns) 
      { 
       var ColumnName = column.ColumnName; 
       var ColumnData = row[column].ToString(); 
       var currentElement = Regex.Replace(element.Field_Label, @"\W", ""); 

       if (element.Module_Field_ID != null) 
       { 

        if (currentElement == ColumnName) 
         element.ColumnValue = ColumnData;         
       } 
       else 
       { 
        if (element.Field_Type_Name != "Checkbox") 
        { 
         if ("Q_" + element.Column_Name_ID == ColumnName) 
          element.ColumnValue = ColumnData; 
        } 
        else 
        { 
         if ("Q_" + element.Column_Name_ID + "_" + element.Value_Column_Name_ID == ColumnName) 
            element.ColumnValue = ColumnData; 
        } 
       } 
     } 
    } 
} 

나는 List of object (EPSElement)를 가지고 있습니다. EPSElement에는 데이터 테이블 (dt = ds.Tables [1];)에서 데이터를 가져 오는 ColumnValue 필드가 있습니다. 이것을 달성하기 위해 foreach 루프를 사용하고 있습니다.이 작업을 수행하는 더 좋은 방법이 있습니까? 각 루프마다 세 가지로 너무 만족하지 않습니다. LINQ로 바꿀 수 있습니까?foreach를 linq으로 바꿉니다

+1

'element.ColumnValue'의 값을 각 행의 데이터로 반복해서 대체하는 것처럼 보입니까? – Guvante

+0

@Guvante 예 – DotNetBeginner

답변

2

이것은 상당히 잘 번역됩니다. foreach -es 각각은 from으로 변환되며, 몇 가지 변수는 각각 let이고, if은 모두 where입니다.

var query = from element in elementList 
      from row in dt.Rows.Cast<DataRow>() 
      from column in dt.Columns.Cast<DataColumn>() 
      let ColumnName = column.ColumnName 
      let ColumnData = row[column].ToString() 
      let currentElement = Regex.Replace(element.Field_Label, @"\W", "") 
      where (element.Module_Field_ID != null && currentElement == ColumnName) 
      || (element.Field_Type_Name != "Checkbox" 
        && "Q_" + element.Column_Name_ID == ColumnName 
       || element.Field_Type_Name == "Checkbox" 
        && "Q_" + element.Column_Name_ID + "_" + element.Value_Column_Name_ID == ColumnName) 
      select new { Element = element, ColumnData = ColumnData }; 

foreach (var item in query) 
    item.Element.ColumnValue = item.ColumnData; 

참고 Where의 논리가 조금 복잡한이기 때문에, 그것은 당신이 같은 것을 가지고있는 그것의 자신의 방법으로 그것을 밖으로 리팩토링하는 것이 가장 수 있음 : 다음

where IsValid(element, ColumnName, currentElement) 

구현 할 수 있습니다 내 쿼리 또는 원본 코드의 논리에 따라 원하는 것을 기반으로하십시오.

+1

이것이 더 나은지 (선명도, 유지 보수 등) 있는지 여부는 논쟁의 여지가 있습니다. – jason

+1

@Jason 분명히 논쟁의 여지가 있지만, LINQ를 사용하여 이것이 어떻게 구현되는지 보여줌으로써 그는 이제 두 가지를 비교할 수있게되었고, 그가 선호할지 여부에 대한 판단을 내릴 수있게되었습니다. 내 편집을 보지 못했다면, 나는 그 방법을 점검하는 것을 리팩토링하고 싶을 것입니다. – Servy

+0

@Servy : 또한 첫 번째 줄이'elementList의 요소에서부터 '로 비슷하게 변경되면'new {Element, ColumnData}'를 선택하는 것을 단순화 할 수 있다는 점도 언급 할 필요가 있습니다 (즉, 명시적인 선언은 필요 없습니다). 그게 좋든 싫든 개인적인 취향이지만 그게 더 명확 해 지는데 도움이된다고 생각합니다. –

5

나는 이 아니며은 LINQ로 바꾸려고합니다. 먼저, foreach의 본문 내부에서 돌연변이를 일으키고 있습니다. 입니다. LINQ를 사용하려고 시도했습니다. LINQ는 쿼리에 관한 것입니다 (LIN Q의 Q는 q입니다) 부작용이 없어야합니다. 그러나 당신이 돌연변이를 새로운 순서의 투영법으로 대체하고 LINQ로 변환하면 이 매우이됩니다. 너무 많은 중첩 된 논리. 그냥 놔둬.

+0

고맙습니다. 제이슨, 잠시 동안이 코드를 그대로 두었습니다. 그러나 어떤 이유로 3 개의 foreach가 나에게 도청당했습니다. 그것을 떠난 이후로 좋은 생각은 내가 찾고 있던 유효성 검사 였고 이제 잔소리없는 의심없이 코딩으로 계속 전진 할 수있다. – DotNetBeginner

+0

+1 부작용 이외에도 내가 본다면 살아야한다는 의지를 잃어 버릴 것이라고 생각한다. linq ... –

+1

@Neha, 정말로 "겉치레 정리"를 원한다면, 가장 내부의 foreach 루프를'void ProcessRow (EPSFromElement element, DataRow row)'라는 자체 함수로 이동하십시오. 블록을 강조 표시하면 'rt-click-> Refactor-> Extract Method'가 쉽게이를 수행 할 수 있어야합니다. 나는 깊은 깊은 둥지가있는 경우에 읽는 것이 더 쉽게하기 위하여 때때로 이것을 할 것이다. –

관련 문제