2012-04-11 3 views
5

나는 대답을 찾지 못했습니다.Java for 루프 VS .NET foreach 루프

class Car { 
    /* car stuff */ 
} 

그리고 자바

class Truck extends Car { 
    /* truck stuff */ 
} 

다음 작품 잘 C#에서 C#

class Truck : Car { 
    /* truck stuff again */ 
} 

에서 :

의 우리가 자바 나 C#을 하나에서 다음과 같은 코드가 있다고 가정 해 봅시다
List<Car> carList = new List<Car>(); 
//add some objects to the collection 
foreach(Truck t in carList) 
    //do stuff with only the Truck objects in the carList collection 

이 작업은 Truck이 Car의 하위 클래스이기 때문에 간단한 용어로 각 트럭이 Car이라는 의미입니다. 문제는 그 유형 검사가 완료되고 trucks 만 carList에서 선택된다는 것입니다. 우리가 자바에서 같은 일을하려고하면

: 때문에 강화 된 루프 내부의 코드의

List<Car> carList = new ArrayList<Car>(); 
//add some objects to the collection 
for(Truck t : carList) 
    //**PROBLEM** 

를, 코드도 컴파일되지 않습니다. 대신 우리는 같은 효과를 얻기 위해 이런 일을 할 필요가 :

for(Car t : carList) 
    if(t instanceof Car) 
     //cast t to Truck and do truck stuff with it 

그것은 C에서 #은 아무 문제없이 작동하는 같은 생각이지만, 자바에서 당신은 여분의 코드가 필요합니다. 구문조차도 거의 같습니다! Java에서 작동하지 않는 이유가 있습니까?

+1

이것은 또한 C#에서 그렇게 깨끗하지 않다 정말 신중하다. Java는 더 신중 해 보이며 프로그래머가 먼저 확인하기를 원합니다 (물론 C# 버전은 자신이하는 일을 알고있는 경우 이점을 추가합니다). –

+0

C#에서 각 개체의 형식이 검사됩니다. 트럭 인 경우 foreach 루프의 본문이 입력되고 그렇지 않은 경우 루프가 시작됩니다. 그것에 대해 깨끗하지 않은 것은 무엇입니까?내가 (Java)를 체크하거나 런타임이 그것을 체크 (C#)하면 그것은 같은 최종 결과이다. – alegen

+0

@alegen, 그건 사실이 아닙니다. –

답변

7

하지만, 그 유형 확인이 이루어지며 carList에서 트럭 만 선택됩니다.

아니요. 목록에 Truck을 제외한 것이 있으면 런타임 예외가 C#에서 발생합니다. 당신은 주조 및 유형 검사를 직접 확인해야합니다 : 기본적으로, C#으로는

foreach(object _t in carList) { 
    Truck t = (Truck)_t;  // throws an InvalidCastException if _t is not a Truck 
    ... 
} 

자바 변형처럼

foreach(Truck t in carList) { 
    ... 
} 

동작합니다 다음, 다른 한편으로는, 입력 - 안전합니다.


Java와 C#은 왜 다르게 동작합니까? 이것은 제 추측입니다 제네릭이 있기 전에

C#은 foreach 키워드를 가졌습니다. 따라서 List<Car>을 가질 가능성은 없습니다. C 번호는 foreach의 자바 방법을 선택했다했다면, 당신은 성가신

foreach(object _c in myArraylistContainingOnlyCars) { 
    Car c = (Car)_c; 
    // do something with c 
} 

를 작성해야 할 것이다. 반면에 확장 된 for 루프와 제네릭은 Java에서 동일한 버전 (Java 5)으로 도입되었으므로 자동 형 변환이 필요하지 않았습니다.C#에서

+0

그래서 목록에 트럭 개체가 없으면 예외가 발생합니다. – alegen

+1

아니요, 트럭이 아닌 객체가 있으면 예외가 던져 질 것입니다. –

+0

시도해 보았고 올바른 답변입니다. 답변을 주셔서 감사합니다. – alegen

4

, 당신은

foreach(Truck t in carList) 

어떤 컴파일러가 이해하는 것은 (약)이다

쓰기 : carList 비 트럭 자동차가 포함되어있는 경우 할당이 런타임에 실패합니다

var enumerator = carList.GetEnumerator(); 

while (enumerator.MoveNext()) 
{ 
    Truck t = (Truck)enumerator.Current; 
    // do stuff 
} 

합니다.

당신은 설명하기 위해 다음과 같은 콘솔 응용 프로그램을 시도 할 수 있습니다 : 언어를 설계 할 때 다른 선택이되었습니다 때문에

namespace ConsoleApplication1 
{ 
    class Car 
    { 
    } 

    class Truck: Car 
    { 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      Car[] cars = new[] { new Car(), new Truck() }; 

      foreach (Truck t in cars) 
      { 
       Console.WriteLine("1 truck"); 
      } 

      Console.Read(); 
     } 
    } 
} 

는 C#과 자바 컴파일러가 다르게 여기에 작동합니다. 이상하게도 "가능한 한 빨리 컴파일 시간에 실패"는 C# 사양의 일반적인 지침입니다. 다음은 적용되지 않는 케이스입니다. C# 언어를 좋아하는만큼 Java 동작을 선호합니다. 열거 가능한 필터링됩니다 만 트럭 루프에 그것을 만들 것입니다

foreach (Truck t in carList.OfType<Truck>()) 
{ 
    //do stuff 
} 

그 방법 :

그러나, C#으로, LINQ는 당신이 그것을 가지고 생각 functionnality을 달성 할 수있는 쉬운 방법을 제공합니다.

2
List<Car> carList = new ArrayList<Car>(); 
//add some objects to the collection 
for(Truck t : carList) 
    //**PROBLEM** 

Java 5에 도입 된 Java Generics는 .NET generics와는 조금 다릅니다.

짧은 이야기 - 이처럼 코드를 작성할 수 없습니다. 컴파일 타임 오류입니다. 당신은 자동차의 목록이 있고 트럭의 목록을하려고 - 심지어/

올바른 접근 방식은 Car 인터페이스를 통해 Truck 클래스를 사용하는 것입니다 잘못된 소리. (메서드 또는 메서드가 다른 의미가 충분하지 않은 경우) 반복 할 수 없으면 목록을 필터링하거나 클래스를 다시 디자인 할 수 있습니다.

1

Car 대신 Truck 클래스를 사용하기 때문에 프로그램이 컴파일되지 않습니다.

당신은 다음과 같이 할 수있는이 일

for(Car t : carList) { 
    if(t instanceof Car) 
     // Do stuff here 
} 

필요 없음 :

for(Car t : carList) { 
    // Do stuff here 
} 

그것은 것입니다 작품이 같이 할 경우 :

List<Truck> truckList = new ArrayList<Truck>(); 

for(Car car : truckList) { 
    // Do stuff here 
} 

또는이 :

List<Car> carList = new ArrayList<Car>(); 

for (Iterator<Car> it = carList.iterator(); it.hasNext();) { 
    Truck car = (Truck) it.next(); 
    // Do stuff here 
} 
대신이의

: 모든 트럭은 자동차입니다하지만 모든 차량은이 트럭 ... C#으로 변환이 런타임에 시도되지만, 당신이해야하기 때문에

List<Car> carList = new ArrayList<Car>(); 

for(Truck truck : carList) { 
    // Do stuff here 
}