2012-04-11 15 views
5

मेरे पास एक प्रश्न है जिसके लिए मुझे कोई जवाब नहीं मिला है।जावा लूप वीएस के लिए बढ़ाया गया .NET foreach loop

class Car { 
    /* car stuff */ 
} 

और फिर जावा

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

और सी #

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

सी # निम्न काम करता है ठीक में:

मान लीजिए कि हम या तो जावा या सी # में निम्न कोड डालें
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 

यह काम करता है क्योंकि ट्रक कार का उप-वर्ग है जो सरल शब्दों में है कि प्रत्येक ट्रक भी एक कार है। बात यह है कि, उस प्रकार की जांच की जाती है और केवल कारलिस्ट से ट्रक का चयन किया जाता है।

हम जावा में एक ही बात की कोशिश करते हैं: बढ़ाया पाश अंदर कोड की वजह से

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 

यह एक ही विचार सी में # किसी भी समस्या के बिना काम करता है जो है, लेकिन जावा में आप अतिरिक्त कोड की जरूरत है। यहां तक ​​कि वाक्यविन्यास लगभग समान है! क्या कोई कारण है कि यह जावा में काम नहीं करता है?

+1

यह भी सी # में इतना साफ नहीं है के बाद से हर ट्रक एक कार है, लेकिन नहीं हर कार एक ट्रक ... सी # में रूपांतरण कार्यावधि में करने की कोशिश की है, लेकिन आप होना चाहिए वास्तव में इसके साथ सतर्क। जावा इसके बारे में अधिक सतर्क प्रतीत होता है और प्रोग्रामर को पहले यह जांचना चाहता है (निश्चित रूप से सी # संस्करण कुछ लाभ जोड़ता है यदि आप जानते हैं कि आप क्या कर रहे हैं)। सी # में –

+0

प्रत्येक ऑब्जेक्ट के प्रकार की जांच की जाती है। यदि यह ट्रक है, तो फ़ोरैच लूप का शरीर दर्ज किया जाता है, अन्यथा यह नहीं होता है। इसके बारे में क्या साफ नहीं है?या तो मैं इसे (जावा) या रनटाइम चेक करता हूं (सी #) यह वही अंतिम परिणाम है। – alegen

+0

@alegen, यह सच नहीं है। –

उत्तर

7

हालांकि, यह टाइपिंग जांच की जाती है और केवल कारलिस्ट से ट्रक का चयन किया जाता है।

नहीं, ऐसा नहीं है। यदि आपकी सूची में Truck एस है लेकिन सी # में रनटाइम अपवाद होगा। आप कलाकारों और प्रकार की जाँच अपने आप को करना है: मूल रूप से, सी # में, जैसे

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

जावा संस्करण निम्नलिखित

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

बर्ताव करता है, दूसरे हाथ पर, टाइप-सुरक्षित है।


तो, जावा और सी # अलग तरीके से क्यों व्यवहार करते हैं? यह मेरा अनुमान है:

सी # जेनरिक्स से पहले foreach कीवर्ड था। इस प्रकार, List<Car> होने की कोई संभावना नहीं थी। अगर सी # foreach के जावा तरीका के लिए चुना था, तो आप

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

जो कष्टप्रद है लिखने के लिए होगा। दूसरी तरफ, जावा में एक ही संस्करण (जावा 5) में लूप और जेनेरिक के लिए विस्तारित किया गया था, इसलिए स्वचालित कास्ट की आवश्यकता नहीं थी।

+0

तो आपका मतलब है कि अगर सूची में कोई ट्रक ऑब्जेक्ट नहीं है, तो एक अपवाद फेंक दिया जाएगा? – alegen

+1

नहीं, यदि इसमें कोई गैर-ट्रक वस्तु है, तो –

+0

को एक अपवाद फेंक दिया जाएगा और यह सही है ... मेरे सी # पर ब्रश करना चाहिए, आपके उत्तर के लिए धन्यवाद! – alegen

4

सी # में, जब आप

foreach(Truck t in carList) 

क्या संकलक समझता है (लगभग) है लिखें:

var enumerator = carList.GetEnumerator(); 

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

काम रनटाइम पर विफल हो जाएगा यदि carlist गैर ट्रक कारों में शामिल है।

आप वर्णन करने के लिए निम्नलिखित सांत्वना आवेदन कोशिश कर सकते हैं:

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(); 
     } 
    } 
} 

सी # और जावा compilers अलग तरह से व्यवहार करते हैं यहाँ क्योंकि विभिन्न विकल्पों जब भाषा को डिजाइन किया गया है। विचित्र रूप से पर्याप्त, "यथासंभव जल्द से जल्द विफल, समय पर संकलन समय पर" सी # विनिर्देशों में एक आम दिशानिर्देश है। यहां एक ऐसा मामला है जहां यह लागू नहीं होता है और जहां, मुझे सी # भाषा पसंद है, मैं जावा व्यवहार पसंद करता हूं।

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

कि जिस तरह से गणनीय फ़िल्टर कर दिया जाएगा और केवल ट्रकों पाश करने के लिए यह कर देगा:

हालांकि, सी # में, LINQ functionnality आप सोचा था कि यह था प्राप्त करने के लिए एक आसान तरीका प्रदान करता है।

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

जावा जेनिक्स, जावा 5 में पेश किया गया, .NET जेनरिक से थोड़ा अलग है।

लंबी कहानी छोटी - आप इस तरह के कोड नहीं लिख सकते - यह एक संकलन-समय त्रुटि है। आप कारों की एक सूची है और आप ट्रकों की एक सूची प्राप्त करने की कोशिश - यह और भी गलत लगता है/

सही दृष्टिकोण अपने Car इंटरफ़ेस के माध्यम से Truck वर्ग का प्रयोग है। यदि आप नहीं कर सकते (पर्याप्त विधियों या विधियों के अलग-अलग अर्थ नहीं हैं) तो आप या तो सूची को फ़िल्टर कर सकते हैं (पुनरावृत्ति से पहले) या .. अपनी कक्षाओं को फिर से डिजाइन करें

1

प्रोग्राम संकलित नहीं होगा क्योंकि आप कार के बजाए ट्रक क्लास का उपयोग कर रहे हैं।

यह एक

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 
} 
इसके बजाय इस बात का

:

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

for(Truck truck : carList) { 
    // Do stuff here 
} 
संबंधित मुद्दे