2010-12-05 5 views
2

항목 목록을 반복하려고합니다. 항목은 모두 공통 인터페이스의 일부입니다. 그들은 this question에 설명되어 있습니다. foreach 루프를 사용하여 루프를 진행하지만 어떤 유형인지에 따라 다른 동작을 실행합니다.다른 데이터 유형의 목록 반복?

ProcessLine(MachineLine ML); //For MachineLines 
ProcessLine(MachineCircle MC); //For MachineCircles 

방법이 반복은 여러 데이터 유형을 고려하여 수행 할 수 있습니다 단순화하기 위해

,의는 다음과 같이 내가 실행하려는 행동이 가정 해 봅시다?

답변

2

적절한 오버로드를 ProcessLine()으로 정의했다고 가정하면 각 반복 중에 이러한 개체의 유형을 테스트 한 다음 그에 따라 캐스팅하고 메서드를 호출하기 만하면됩니다. 이런 식으로 뭔가 :

foreach (IMachine m in machineList) { 
    if (m is MachineLine) { 
     ProcessLine((MachineLine) m); 
    } else if (m is MachineCircle) { 
     ProcessLine((MachineCircle) m); 
    } 
} 

이 프로그램 디자인을 개선하기 위해, 당신은 (당신의 인터페이스에 Process() 방법을 추가하는 등) 여기에 다른 제안을 고려하실 수 있습니다. 문제는이 상황에서 가장 적합한 디자인의 경우

+0

와우에서 작업하는 경우, 동적 키워드를 사용할 수 있습니다! 거의 같은 코드 :) – Lorenzo

+0

@Lorenzo : 처음에는'instanceof'도 썼지 만 실제로는'is'입니다. 당신의 코드도 고쳐 줄 수 있습니다 :) – BoltClock

+0

+1 절대적으로 맞습니다! ;) – Lorenzo

1
List<IMachine> m = new List<IMachine>(); 
foreach (IMachine machine in m) { 
    if (m is MachineLine) { 
     ProcessLine(m as MachineLine); 
    } 
    else if (m is MachineCircle) { 
     ProcessLine(m as MachineCircle); 
    } 
} 
+0

'm as MachineLine'에서 '(MachineLine) m'으로 캐스트를 변경합니다. 이미 객체의 유형을 확인했으며 'as'를 사용하면 해당 검사 만 반복합니다. – TheEvilPenguin

+0

IMO 또한'(MachineLine) m'을 사용하는 2 개의 캐스트 연산이 있습니다 – Lorenzo

+1

* 모두 *와 * as *는 캐스트 연산을 수행합니다. 1 캐스트 만하려면 * as *를 사용해야하지만 결과를 변수에 보관해야하며 * is *를 사용하는 대신 변수를 * null *과 비교하십시오. – Ran

4

나는 심각 고려할 것입니다. IMachine 인터페이스에 Process 메소드가 없어야합니까? 각 시스템은 적절하게이 문제를 구현할 수, 다음 루프는된다 :

어쨌든
foreach (IMachine machine in machines) 
{ 
    machine.Process(); 
} 

는 질문에 대답하도록 요청으로, 여기 한 가지 방법이 있습니다. 아이디어는 성공할 때까지 또는 우리가 옵션을 벗어날 때까지 목표 유형으로 "투기 주조"를 계속 시도하는 것입니다. 이는 일반적으로 as 연산자로 수행 한 다음 null 검사를 수행합니다.

IList<IMachine> machines = ... 

foreach (IMachine machine in machines) 
{ 
    MachineLine machineLine = machine as MachineLine; 

    if (machineLine != null) 
     ProcessLine(machineLine); 

    else 
    { 
     MachineCircle machineCircle = machine as MachineCircle; 

     if (machineCircle != null) 
      ProcessCircle(machineCircle); 

     else throw new UnknownMachineException(...); 
    } 
} 

이 패턴은 추악합니다. 더 깔끔한 솔루션의 경우 많은 수의 구현자가있는 경우 C# - Is there a better alternative than this to 'switch on type'을 살펴볼 수도 있습니다.

+1

첫 번째 단락에서'IMachine.Process()'메소드를 제안하는 +1. – BoltClock

1
foreach (var m in list){ 
    if (m is MachineLine) ProcessLine((MachineLine) m); 
    else if (m is MachineCircle) ProcessLine((MachineCircle) m); 
} 
0

대신 IMachine을 허용하도록 ProcessLine 메소드를 변경하고 유형에 따라 다른 메소드를 호출해야합니다. 코드가 명확 해지면 나중에 다른 곳에서 논리를 재사용 할 수 있습니다. 이처럼 :

foreach (IMachine m in machineList) 
     ProcessLine(m); 

는 ProcessLine의 코드가 보일 것 같은이도 ... 방문자 디자인 패턴에 대한 좋은 후보처럼 소리

void ProcessLine(IMachine machine) 
{ 
    if (machine is MachineLine) 
     ProcessMachineLine(MachineLine) 
    else if (machine is MachineCircle) 
     ProcessMachineCircle(MachineCircle) 
} 
2

이 IMHO를 처리하는 가장 좋은 방법은 원하는 동작을 수행하는 메소드가있는 공통 기본 클래스/인터페이스에서 유형을 상속받는 것입니다. 그런 다음 루프 내에서 공통 메소드를 호출하십시오. 귀하의 경우, 나는 기본 클래스로 만들 것이고, 이것은 is-a 관계이므로 ProcessLine() 메서드를 기본 클래스에 추가해야합니다.

public abstract class MachineShape 
{ 
    public abstract void ProcessLine(); 
} 

public class MachineLine : MachineShape 
{ 
    public override void ProcessLine() 
    { 
     // implement for MachineLine 
    } 

    public double X1; 
    public double Y1; 
    public double X2; 
    public double Y2; 
    public double Thickness; 
} 

public class MachineCircle : MachineShape 
{ 
    public override void ProcessLine() 
    { 
     // implement for MachineCircle 
    } 

    public double CenterX; 
    public double CenterY; 
    public double Radius; 
} 

MachineShape[] shapes = ...; 
foreach (var shape in shapes) 
{ 
    shape.ProcessLine(); 
} 

다형성을 수행하십시오.

0

Jeff의 솔루션이 가장 먼저 선택되었습니다. 또는 현재 변경하기에는 너무 많은 경우 함수 오버로딩을 사용할 수도 있습니다.

foreach (IMachine m in machineList){ 
     //sorry I can't test it since I don't have visual studio installed. 
     //but you get the idea 
     ProcessLine((m.getType())m); 
} 

function ProcessLine(MachineLine m) 
{ 
... 
} 

function ProcessLine(MachineCircle m) 
{ 
.... 
} 
0

당신이

4.0 .NET
foreach (dynamic m in machineList) { 

if(m.GetType()==typeof(MachineLine)) 
{ 
    // code goes here 
} 
else if(m.GetType()==typeof(MachineCircle)) 
{ 
    // code goes here 
} 

} 
관련 문제