एक परम वस्तु [] को एक वस्तु को कैसे पास किया जाता है []


124

मेरे पास एक तरीका है जो परम ऑब्जेक्ट लेता है [] जैसे:

void Foo(params object[] items)
{
    Console.WriteLine(items[0]);
}

जब मैं इस विधि में दो ऑब्जेक्ट सरणियाँ पास करता हूं, तो यह ठीक काम करता है:

Foo(new object[]{ (object)"1", (object)"2" }, new object[]{ (object)"3", (object)"4" } );
// Output: System.Object[]

लेकिन जब मैं किसी एक वस्तु को पास करता हूं [], तो यह मेरी वस्तु [] को पहले परम के रूप में नहीं लेता है, इसके बजाय इसके सभी तत्वों को लेता है जैसे कि मैं उन्हें एक-एक करके पास करना चाहता था:

Foo(new object[]{ (object)"1", (object)"2" });
// Output: 1, expected: System.Object[]

मैं किसी भी वस्तु को पारस सरणी के पहले तर्क के रूप में [] कैसे पास करूं?

जवाबों:


99

एक सरल टाइपकास्ट सुनिश्चित करेगा कि कंपाइलर जानता है कि इस मामले में आपका क्या मतलब है।

Foo((object)new object[]{ (object)"1", (object)"2" }));

जैसा कि एक सरणी वस्तु का एक उपप्रकार है, यह सब काम करता है। एक अजीब समाधान के बिट हालांकि, मैं सहमत हूँ।


2
जिस तरह से परमेस काम करता है वह अनावश्यक लगता है, और उप-विषयक c # डिज़ाइन, जो हमें अन्य भाषाओं में उपयोग करने के लिए दिया जाता है। केवल एक ही रूप को स्वीकार करने के लिए परमेस बनाया जा सकता था, और एक सुविधा की तरह एक प्रसार को जोड़ा जा सकता था जो पूरी भाषा को लाभ पहुंचाएगा, न कि केवल इस मामले में। उदाहरण के लिए, हम सभी परम कॉल को फू (obj [0], obj [1]) होने के लिए बाध्य कर सकते हैं, और फिर एक अलग प्रसार ऑपरेटर को Foo (... obj) की अनुमति दे सकते हैं।
व्हाइटनीलैंड

1
एहसास हुआ कि मैंने स्पष्ट नहीं किया है कि मेरे पास andjjsberg के लिए बहुत सम्मान है, वह दुनिया के सर्वश्रेष्ठ भाषा डिजाइनरों में से एक है। लेकिन हम किसी के काम में सुधार के बारे में सोच सकते हैं जो पर्याप्त दृष्टि प्रदान करता है, इसलिए प्रौद्योगिकी।
व्हाइटनीलैंड

74

paramsपैरामीटर संशोधक कॉल करने के लिए एक विधि के लिए कई तर्क पारित करने के लिए एक शॉर्टकट वाक्य रचना देता है। एक paramsपैरामीटर के साथ एक विधि को कॉल करने के दो तरीके हैं :

1) पैरामीटर प्रकार की एक सरणी के साथ कॉल करना, जिस स्थिति में paramsकीवर्ड का कोई प्रभाव नहीं पड़ता है और सरणी सीधे विधि से पारित हो जाती है:

object[] array = new[] { "1", "2" };

// Foo receives the 'array' argument directly.
Foo( array );

2) या, तर्कों की एक विस्तारित सूची के साथ कॉल करना, जिस स्थिति में कंपाइलर स्वचालित रूप से एक अस्थायी सरणी में तर्कों की सूची को लपेट देगा और उस विधि को पास करेगा:

// Foo receives a temporary array containing the list of arguments.
Foo( "1", "2" );

// This is equivalent to:
object[] temp = new[] { "1", "2" );
Foo( temp );


ऑब्जेक्ट सरणी में पास करने के लिए " params object[]" पैरामीटर के साथ एक विधि में , आप या तो कर सकते हैं:

1) मैन्युअल रूप से एक रैपर सरणी बनाएं और उस विधि को सीधे पास करें, जैसा कि लेससेव ने उल्लेख किया है :

Foo( new object[] { array } );  // Equivalent to calling convention 1.

2) या, आदमobject द्वारा उल्लिखित तर्क को , जिस स्थिति में कंपाइलर आपके लिए आवरण सरणी बनाएगा:

Foo( (object)array );  // Equivalent to calling convention 2.


हालाँकि, यदि विधि का लक्ष्य कई ऑब्जेक्ट सरणियों को संसाधित करना है, तो इसे स्पष्ट " params object[][]" पैरामीटर के साथ घोषित करना आसान हो सकता है । यह आपको कई सरणियों को तर्क के रूप में पारित करने की अनुमति देगा:

void Foo( params object[][] arrays ) {
  foreach( object[] array in arrays ) {
    // process array
  }
}

...
Foo( new[] { "1", "2" }, new[] { "3", "4" } );

// Equivalent to:
object[][] arrays = new[] {
  new[] { "1", "2" },
  new[] { "3", "4" }
};
Foo( arrays );

संपादित करें: रेमंड चेन इस व्यवहार का वर्णन करता है और यह एक नई पोस्ट में C # विनिर्देश से संबंधित है ।


8

यह एक पंक्ति समाधान है जिसमें LINQ शामिल है।

var elements = new String[] { "1", "2", "3" };
Foo(elements.Cast<object>().ToArray())


2

इस समस्या को हल करने का एक और तरीका (यह इतना अच्छा अभ्यास नहीं है लेकिन सौंदर्य दिखता है):

static class Helper
{
    public static object AsSingleParam(this object[] arg)
    {
       return (object)arg;
    }
}

उपयोग:

f(new object[] { 1, 2, 3 }.AsSingleParam());

1

एक विकल्प यह है कि आप इसे दूसरे सरणी में लपेट सकते हैं:

Foo(new object[]{ new object[]{ (object)"1", (object)"2" } });

बदसूरत की तरह, लेकिन जब से प्रत्येक आइटम एक सरणी है, तो आप इसे समस्या को दूर करने के लिए बस नहीं डाल सकते हैं ... जैसे कि अगर यह फू (परम ऑब्जेक्ट्स आइटम) थे, तो आप बस कर सकते हैं:

Foo((object) new object[]{ (object)"1", (object)"2" });

वैकल्पिक रूप से, आप फू के एक और अतिभारित उदाहरण को परिभाषित करने का प्रयास कर सकते हैं, जिसमें सिर्फ एक सरणी होती है:

void Foo(object[] item)
{
    // Somehow don't duplicate Foo(object[]) and
    // Foo(params object[]) without making an infinite
    // recursive call... maybe something like
    // FooImpl(params object[] items) and then this
    // could invoke it via:
    // FooImpl(new object[] { item });
}

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.