2012-01-17 10 views
32

इन दो पंक्तियों के बीच कोई अंतर नहीं है, क्योंकि दूसरी पंक्ति में कंपाइलर समझता है कि यह int प्रकार की एक सरणी है।संकलक var [] ऑब्जेक्ट [] में C# में क्यों परिवर्तित नहीं करता है?

var x = new int[] { 1, 2, 3 }; //Fine, x is int[] 
var x = new [] { 1, 2, 3 };  //Fine, x is int[] 

लेकिन मैं इसे विभिन्न प्रकारों से क्यों नहीं कर सकता? संकलक मेरे चर को ऑब्जेक्ट टाइप करने के लिए क्यों परिवर्तित नहीं करता है?

var x = new object[] { 1, "df", 5 }; //Fine, x is object[] 
var x = new [] { 1, "df", 5 };   //Error! "No best type found for implicity-typed-array" 

संपादित करें:

अपने सभी सवालों के जवाब के लिए धन्यवाद। लेकिन मुझे अभी भी आश्चर्य है कि सभी अभिव्यक्तियों को बनाने के लिए पेशेवर और विपक्ष क्या हैं जो संकलक object टाइप नहीं कर सकते हैं? (क्योंकि मैं var नोटेशन का उपयोग करता हूं जिसका अर्थ है कि यह किसी भी प्रकार का नहीं हो सकता है। मैं इस तरह समझता हूं।) संकलक विरासत के पेड़ पर जाकर सरणी सदस्यों के निकटतम प्रकार क्यों नहीं ढूंढता है?

+2

क्या आपने सी # spec पढ़ा है? – BoltClock

+0

हां, लेकिन ज्यादातर सवाल यह है कि "इस तरह से इसे क्यों लागू नहीं किया जाता है?" –

+2

जॉय के जवाब पर Damien_The_Unbeliever की टिप्पणी यह ​​सब सचमुच कहती है। यह कंपाइलर के लिए बहुत अधिक काम है, न कि उल्लंघनकारी 'ऑब्जेक्ट []' का उल्लेख न करें, नतीजतन मेरे लिए बहुत प्रतिद्वंद्वी है। – BoltClock

उत्तर

38

new [] नोटेशन आपको एक स्पष्ट प्रकार के सरणी सदस्यों को टाइप करने के लिए सहेजने के लिए है (या आपको उन सरणी बनाने की इजाजत देता है जहां इसके तत्वों का गुमनाम प्रकार है), लेकिन इसके प्रकार की अनुमान सीमित है कि सभी तत्वों को समान साझा करना होगा टाइप करें या कम से कम एक सदस्य द्वारा साझा किए गए एक सामान्य प्रकार के लिए पूरी तरह से परिवर्तनीय हो। सी # विशिष्टता देखें, खंड 7.6.10.4:

तीसरे रूप की एक सरणी निर्माण अभिव्यक्ति को एक पूर्ण रूप से टाइप की गई सरणी निर्माण अभिव्यक्ति के रूप में संदर्भित किया जाता है। यह दूसरे रूप के समान है, सिवाय इसके कि सरणी के तत्व प्रकार को स्पष्ट रूप से नहीं दिया गया है, लेकिन सरणी प्रारंभकर्ता में अभिव्यक्ति के सेट के सर्वोत्तम सामान्य प्रकार (§7.5.2.14) के रूप में निर्धारित किया गया है।

निम्नलिखित परोक्ष टाइप किया सरणी निर्माण भाव के उदाहरण हैं:

var a = new[] { 1, 10, 100, 1000 };      // int[] 
var b = new[] { 1, 1.5, 2, 2.5 };       // double[] 
var c = new[,] { { "hello", null }, { "world", "!" } }; // string[,] 
var d = new[] { 1, "one", 2, "two" };      // Error 

पिछले अभिव्यक्ति एक संकलन समय त्रुटि होती है क्योंकि न तो int है और न ही string परोक्ष अन्य के लिए परिवर्तनीय है, और इसलिए वहाँ कोई सबसे अच्छा आम है प्रकार। इस मामले में एक स्पष्ट रूप से टाइप की गई सरणी निर्माण अभिव्यक्ति का उपयोग किया जाना चाहिए, उदाहरण के लिए object[] होने के प्रकार को निर्दिष्ट करना। वैकल्पिक रूप से, तत्वों में से एक को एक सामान्य आधार प्रकार में डाला जा सकता है, जो तब अनुमानित तत्व प्रकार बन जाएगा।

मुख्य बिंदु यह है कि "सबसे अच्छा सामान्य प्रकार" केवल पहले से मौजूद प्रकारों में से एक हो सकता है। ने एक टिप्पणी में बताया: "जैसा कि श्री लिपर्ट को अनुमान के आसपास इंगित करने का शौक है, जब भी यह एक सामान्य आम प्रकार की तलाश में है, तो यह केवल उन प्रकारों में से एक लौटाएगा जो पहले से मौजूद हैं - यह शिकार नहीं करता है सबसे अधिक व्युत्पन्न आम पूर्वज के लिए। "

सिर्फ इसलिए कि प्रत्येक सरणी object [] हो सकती है इसका मतलब यह नहीं होना चाहिए। एक कंपाइलर परिप्रेक्ष्य से जो एक छोटी सी अंतिम रिसॉर्ट पसंद होगी, लेकिन डेवलपर के लिए एक बहुत ही प्रतिद्वंद्वी है, मुझे लगता है।

+0

और क्यों नया [] इस तरह के अभिसरण प्रदान करने के लिए लागू नहीं किया गया है? उसमें विपक्ष क्या है? –

+0

नहीं, नया [] नोटेशन मुख्य रूप से अनाम प्रकारों के सरणी को भरने के लिए है। टाइपिंग सेविंग सिर्फ एक अच्छा साइड इफेक्ट है। – Stilgar

+0

* क्यों * कुछ हो सकता है एरिक लिपर्ट जवाब देने में सक्षम हो सकता है। मैं इतिहास पर थोड़ा अस्पष्ट हूं लेकिन पूर्ण-उड़ा प्रकार अनुमान 'var' के साथ आया था, शायद' नया [] 'यह बताता है। – Joey

18

जोई का जवाब पर विस्तार करने के लिए, इस उदाहरण पर विचार करें:

interface IFoo { } 
interface IBar { } 

class A : IFoo, IBar { } 
class B : IFoo, IBar { } 

var array = new [] { new A(), new B() }; 

दोनों कक्षाएं दोनों इंटरफेस को लागू (और यह भी object से निकाले जाते हैं), तो किस प्रकार array लिए लगाए गए अनुमान किया जाना चाहिए?उनके आधार वर्ग के रूप में

interface IFoo { } 

class A : IFoo { } 
class B : IFoo { } 

var array = new [] { new A(), new B() }; 

दोनों A और B शेयर object, लेकिन यह बेकार हो जाएगा और ज्यादातर:


जहां A और B शेयर सिर्फ एक ही इंटरफ़ेस अपनी टिप्पणी का जवाब करने के लिए, मामले पर विचार सरणी प्रकार के लिए इसका अनुमान लगाने के लिए बेकार। यदि कोई कुछ हो तो IFoo होने की उम्मीद है, इसलिए यह principle of least astonishment का उल्लंघन करेगा। हालांकि, जैसा कि मैंने सचित्र किया है, यह लगातार नहीं किया जा सकता है।

यहां सबसे सुरक्षित और सबसे संगत व्यवहार टाइप प्रकार की अनुमति देने की अनुमति नहीं है।

+1

+1। हम हमेशा भूल जाते हैं कि .NET * करता है * एकाधिक विरासत का समर्थन करता है (हालांकि केवल इंटरफेस के माध्यम से)। – Heinzi

+1

हाँ, ठीक उदाहरण। लेकिन इस उदाहरण में वह वस्तु में परिवर्तित नहीं हो सकता है। वह निकटतम प्रकार को पा सकते हैं जो वे दोनों विरासत में हैं। कई विरासत नहीं हैं, इसलिए वह पेड़ की एक शाखा द्वारा खोज सकते हैं ... –

+0

@mesiesta: उनके पास केवल एक सामान्य आधार * वर्ग * हो सकता है, लेकिन उन्हें अपने लागू इंटरफेस पर प्राथमिकता क्यों लेनी चाहिए? इंटरफेस भी प्रकार हैं। –

संबंधित मुद्दे