अनाम वर्ग की एक सामान्य सूची


416

C # 3.0 में आप निम्न सिंटैक्स के साथ अनाम वर्ग बना सकते हैं

var o = new { Id = 1, Name = "Foo" };

क्या इन अनाम वर्ग को जेनेरिक सूची में जोड़ने का कोई तरीका है?

उदाहरण:

var o = new { Id = 1, Name = "Foo" };
var o1 = new { Id = 2, Name = "Bar" };

List<var> list = new List<var>();
list.Add(o);
list.Add(o1);

एक और उदाहरण:

List<var> list = new List<var>();

while (....)
{
    ....
    list.Add(new {Id = x, Name = y});
    ....
}

2
ध्यान दें कि सभी ऑब्जेक्ट्स को सरणी में समान टाइप किया जाना चाहिए। शायद ही कभी आपको एक कलाकार के साथ मदद करने की आवश्यकता हो सकती है, विशेष रूप से नल के लिएnew[] { new{ Id = (int?)null, Name = "Foo" }, new { Id = (int?)1, Name = "Foo" }}
आरोनॉल्स

1
अनाम प्रकारों को अस्थायी भंडारण के रूप में उपयोग करने के लिए डिज़ाइन किया गया है, ज्यादातर मामलों में आप उन्हें चयन (i => नया {i.ID, i.Name}) का उपयोग करके LINQ चयन कथन में बनाएंगे; जो सही प्रकार की एक IEnumerable वापसी होगी यदि आप एक LINQ.Where बयान में अपने जबकि खंड को फिर से परिभाषित क्या तुमने कभी सूची की आवश्यकता नहीं होना चाहिए और अगर तुमने किया था आप तो बस उस पर ToList कॉल कर सकते हैं
MikeT

जवाबों:


427

तुम यह कर सकते थे:

var list = new[] { o, o1 }.ToList();

इस बिल्ली की चमड़ी उधेड़ने के बहुत सारे तरीके हैं, लेकिन मूल रूप से वे सभी कहीं न कहीं प्रकार का प्रयोग करेंगे - जिसका अर्थ है कि आप एक सामान्य विधि कह सकते हैं (संभवतः एक विस्तार विधि के रूप में)। एक और उदाहरण हो सकता है:

public static List<T> CreateList<T>(params T[] elements)
{
     return new List<T>(elements);
}

var list = CreateList(o, o1);

तुम्हें नया तरीका मिल गया है :)


32
@ डोरपाउट: यह एक सरणी देगा, लिस्ट <T> नहीं।
जॉन स्कीट

23
@DHornpout: क्या आपके पास "System.Linq का उपयोग करना है?" आपकी फ़ाइल के शीर्ष पर? ToList एक LINQ ऑपरेटर है।
जॉन स्कीट

5
समझ गया .. इसमें "System.Linq का उपयोग करके" शामिल करने की आवश्यकता है। धन्यवाद।
DHornpout

2
यह विजुअल स्टूडियो में एक असंगतता प्रतीत होती है, यह है कि इंटेलीजेंस अनुपलब्ध संदर्भ विधियों के साथ असेंबलियों को शामिल करने को उजागर करने में अधिक सहायक नहीं है (जैसे कि संदर्भित प्रकार)।
LOAS

3
यह आदमी हर जगह है, आज 8 सवाल खोजे, 7 उसके द्वारा उत्तर दिए गए।
कुगन कुमार

109

यहाँ जवाब है।

string result = String.Empty;

var list = new[]
{ 
    new { Number = 10, Name = "Smith" },
    new { Number = 10, Name = "John" } 
}.ToList();

foreach (var item in list)
{
    result += String.Format("Name={0}, Number={1}\n", item.Name, item.Number);
}

MessageBox.Show(result);

12
दत्त, आपका कोड अंत में .TLList () के बिना काम करना चाहिए।
DHornpout

3
ठीक है, अब हमें नई {} लाइनों की जगह एक उदाहरण का चयन करने की आवश्यकता है। var सूची = sourceList.Select (o => new {o.ModelId, o.PartNumber, o.Quantity})। ToList ();
topwik

@ इसके बारे में कोई समाधान?
कीकेनेट

@ दत्त, कोई भी नमूना अगर मैं एक विधि (फ़ंक्शन) का उपयोग करता हूं जो सूची <T> लौटाता है?
किकेनेट

अब विधि string.Joinऔर स्ट्रिंग प्रक्षेप हैं, इसलिए उपयोग करने की आवश्यकता नहीं है foreachऔर Format
realsonic

61

ऐसा करने के कई तरीके हैं, लेकिन यहां कुछ प्रतिक्रियाओं में एक सूची बनाई जा रही है जिसमें कचरा तत्व शामिल हैं, जिससे आपको सूची को खाली करने की आवश्यकता होती है।

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

यहां खाली सूची बनाने के लिए वन-लाइनर दिया गया है:

 var emptyList = new List<Tuple<int, string>>()
          .Select(t => new { Id = t.Item1, Name = t.Item2 }).ToList();

फिर आप इसे अपने सामान्य प्रकार का उपयोग करके जोड़ सकते हैं:

 emptyList.Add(new { Id = 1, Name = "foo" });
 emptyList.Add(new { Id = 2, Name = "bar" });

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

 var emptyList = new List<object>()
          .Select(t => new { Id = default(int), Name = default(string) }).ToList();   

1
मुझे यह तरीका बहुत पसंद है। धन्यवाद पॉल! यह हमेशा एक अच्छा दिन होता है जब आप टुपल्स का उपयोग कर सकते हैं! xD
ब्रैडी लील्स

यह मुझे पंसद है। मैं जिस वस्तु से गुजरने जा रहा हूं, उसके बारे में किसी तरह की ठोस घोषणा करना अच्छा है।
मोरवेल

नाइस मैंने सिर्फ
राइटिंग

विचार के लिए धन्यवाद। एक सुझाव, यदि आप उपयोग करते हैं तो आप डमी सूची को आवंटित करने से बच सकते हैंEnumerable.Empty<object>().Select(o=>definition).ToList()
ब्रेनस्टॉर्म।

45

बिल्कुल नहीं, लेकिन आप कह सकते हैं List<object>और चीजें काम करेंगी। हालांकि, list[0].Idकाम नहीं करेगा।

यह एक होने से C # 4.0 में रनटाइम पर काम करेगा List<dynamic>, कि आप IntelliSense नहीं मिलेगा।


यह दृढ़ता से टाइप नहीं किया गया है, हालांकि, इस अर्थ में कि आपके पास सूची में आइटम के लिए कोई कंपाइलर इंटेलीसेंस समर्थन नहीं होगा।
जोएल कोएहॉर्न

31
इस तरह की चीजें मुझे डर है कि लोग गतिशील होकर करेंगे।
इरिक्कलेन

2
मैंने यह नहीं कहा कि यह एक महान विचार था, लेकिन यह संभव था :-) उदाहरण के लिए रूबी से वस्तुओं को संग्रहीत करने की आवश्यकता हो सकती है।
जेफ मोजर

2
लेकिन उन मामलों में स्रोत प्रकार सभी के बाद गतिशील है, यह गुमनाम प्रकार के लिए एक सूची <गतिशील> का उपयोग करने के लिए कोई मतलब नहीं है।
डाइकम

1
बहुत मददगार। खासतौर पर तब जब लिस्ट को गुमनाम आइटम में जोड़े जाने से पहले परिभाषित किया जाना है।
कार्ल

24

मेरा अनुमान

List<T> CreateEmptyGenericList<T>(T example) {
    return new List<T>();
}

void something() {
    var o = new { Id = 1, Name = "foo" };
    var emptyListOfAnonymousType = CreateEmptyGenericList(o);
}

काम करेगा।

आप इसे इस तरह लिखने पर भी विचार कर सकते हैं:

void something() {
    var String = string.Emtpy;
    var Integer = int.MinValue;
    var emptyListOfAnonymousType = CreateEmptyGenericList(new { Id = Integer, Name = String });
}

हाँ यह समाधान बेनामी सरणी को शुरू करने में मदद करेगा। धन्यवाद।
DHornpout

1
विधि नाम के बाद बस थोड़ा सा <T> डालें।
मार्टिन

21

मैं आमतौर पर निम्नलिखित का उपयोग करता हूं; मुख्यतः क्योंकि आप तब खाली सूची के साथ "शुरू" करते हैं।

var list = Enumerable.Range(0, 0).Select(e => new { ID = 1, Name = ""}).ToList();
list.Add(new {ID = 753159, Name = "Lamont Cranston"} );
//etc.

हाल ही में, मैं इसे इस तरह लिख रहा हूं:

var list = Enumerable.Repeat(new { ID = 1, Name = "" }, 0).ToList();
list.Add(new {ID = 753159, Name = "Lamont Cranston"} );

दोहराने की विधि का उपयोग करने से आप भी कर सकते हैं:

var myObj = new { ID = 1, Name = "John" };
var list = Enumerable.Repeat(myObj, 1).ToList();
list.Add(new { ID = 2, Name = "Liana" });

.. जो आपको पहले से जोड़े गए पहले आइटम के साथ प्रारंभिक सूची देता है।


2
आपको एक रिक्त सूची से शुरू करने की आवश्यकता नहीं है - आप रेंज (0,1) कर सकते हैं और अपनी पहली वस्तु को चुनिंदा कथन में बना सकते हैं .. पहली वस्तु।
मैथ्यू एम।

1
आपको एक खाली सूची से शुरू करने की आवश्यकता नहीं है - उस स्थिति में जहां आप जानते हैं कि पहला आइटम क्या है (उदाहरण के रूप में) तो आप अपनी टिप्पणी में सही हैं। कई बार हालांकि मैं इसे एक मध्यवर्ती फ़ाइल / डेटा स्रोत को पार्स करने के लिए उपयोग करता हूं और LINQ प्रोजेक्शन परिदृश्य में इसका उपयोग करने तक पहले सच्चे आइटम तक नहीं पहुंचता (और इस तरह पहले रिकॉर्ड को लंघन के लिए खाते की आवश्यकता नहीं है)।
रोस्तोव

19

आप अपने कोड में ऐसा कर सकते हैं।

var list = new[] { new { Id = 1, Name = "Foo" } }.ToList();
list.Add(new { Id = 2, Name = "Bar" });

11

नवीनतम संस्करण 4.0 में, नीचे की तरह गतिशील का उपयोग कर सकते हैं

var list = new List<dynamic>();
        list.Add(new {
            Name = "Damith"
    });
        foreach(var item in list){
            Console.WriteLine(item.Name);
        }
    }

10

मैंने कई उत्तरों पर IL की जाँच की। यह कोड कुशलता से एक खाली सूची प्रदान करता है:

    using System.Linq;
    
    var list = new[]{new{Id = default(int), Name = default(string)}}.Skip(1).ToList();

1
मेरे संपादन को अस्वीकार करने का कोई कारण? उत्तर देने के बाद IEnumerable, जबकि मेरा संस्करण लौटता है List, बिल्कुल वही जो ओपी ने पूछा है।
नेक्रोनोमिक्रोन

मैं इस दृष्टिकोण को पसंद करता हूं, या यहां तक ​​कि इस उत्तर के करीब भी new object[] { }.Select(o => new { Id = default(int), Name = default(string) }).ToList()
हूं

8

यहाँ मेरा प्रयास है।

List<object> list = new List<object> { new { Id = 10, Name = "Testing1" }, new {Id =2, Name ="Testing2" }}; 

मैं इस के साथ आया था जब मैंने एक कस्टम प्रकार के लिए बेनामी सूची बनाने के लिए कुछ इसी तरह लिखा था।


8

आप डायनामिक की सूची बना सकते हैं।

List<dynamic> anons=new List<dynamic>();
foreach (Model model in models)
{
   var anon= new
   {
      Id = model.Id,
      Name=model.Name
   };
   anons.Add(anon);
}

"डायनामिक" पहले मूल्य वर्धित द्वारा आरंभ किया जाता है।


7

इसके अलावा:

var o = new { Id = 1, Name = "Foo" }; 
var o1 = new { Id = 2, Name = "Bar" }; 

List <var> list = new List<var>(); 
list.Add(o); 
list.Add(o1);

आप ऐसा कर सकते हैं:

var o = new { Id = 1, Name = "Foo" }; 
var o1 = new { Id = 2, Name = "Bar" }; 

List<object> list = new List<object>(); 
list.Add(o); 
list.Add(o1);

हालाँकि, आपको एक कंपाइलटाइम त्रुटि मिलेगी यदि आप किसी अन्य क्षेत्र में ऐसा कुछ करने की कोशिश करते हैं, हालांकि यह रनटाइम पर काम करता है:

private List<object> GetList()
{ 
    List<object> list = new List<object>();
    var o = new { Id = 1, Name = "Foo" }; 
    var o1 = new { Id = 2, Name = "Bar" }; 
    list.Add(o); 
    list.Add(o1);
    return list;
}

private void WriteList()
{
    foreach (var item in GetList()) 
    { 
        Console.WriteLine("Name={0}{1}", item.Name, Environment.NewLine); 
    }
}

समस्या यह है कि रनटाइम के दौरान केवल ऑब्जेक्ट के सदस्य ही उपलब्ध होते हैं, हालांकि इंटैलिजेंस गुण आईडी और नाम दिखाएगा ।

.Net 4.0 में ऊपर दिए गए कोड में ऑब्जेक्ट के कीवर्ड डायनेमिक istead का उपयोग करने के लिए एक समाधान है ।

गुणों को प्राप्त करने के लिए प्रतिबिंब का उपयोग करने के लिए एक और उपाय है

using System;
using System.Collections.Generic;
using System.Reflection;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Program p = new Program();
            var anonymous = p.GetList(new[]{
                new { Id = 1, Name = "Foo" },       
                new { Id = 2, Name = "Bar" }
            });

            p.WriteList(anonymous);
        }

        private List<T> GetList<T>(params T[] elements)
        {
            var a = TypeGenerator(elements);
            return a;
        }

        public static List<T> TypeGenerator<T>(T[] at)
        {
            return new List<T>(at);
        }

        private void WriteList<T>(List<T> elements)
        {
            PropertyInfo[] pi = typeof(T).GetProperties();
            foreach (var el in elements)
            {
                foreach (var p in pi)
                {
                    Console.WriteLine("{0}", p.GetValue(el, null));
                }
            }
            Console.ReadLine();
        }
    }
}

7

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

var items = "".Select( t => new {Id = 1, Name = "foo"} ).ToList();

यदि आप पहली वस्तु रखना चाहते हैं, तो स्ट्रिंग में केवल एक अक्षर डालें।

var items = "1".Select( t => new {Id = 1, Name = "foo"} ).ToList();

एक सरणी इनिशियलाइज़र के रूप में एक स्ट्रिंग का उपयोग करना काम कर सकता है लेकिन बहुत बुरा अभ्यास है
माइक

मैं कहूंगा कि उपर्युक्त अधिकांश उत्तर विशेष रूप से "अच्छा" अभ्यास नहीं है, लेकिन प्रश्न की प्रकृति के कारण यह एक तरह का था। अनाम प्रकार वास्तव में इस तरह से काम करने के लिए डिज़ाइन नहीं किए गए थे। मैं उत्सुक हूँ, हालांकि मेरी विधि दूसरों की तुलना में "बदतर" क्यों है? मुझे कुछ याद आ रहा है?
ब्रैकस

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

5
var list = new[]{
new{
FirstField = default(string),
SecondField = default(int),
ThirdField = default(double)
}
}.ToList();
list.RemoveAt(0);

5

यह एक पुराना प्रश्न है, लेकिन मुझे लगा कि मैं अपने C # 6 उत्तर में डालूंगा। मुझे अक्सर परीक्षण डेटा सेट करना पड़ता है जो आसानी से इन-कोड में ट्यूपल्स की सूची में दर्ज हो जाता है। विस्तार कार्यों के एक जोड़े के साथ, प्रत्येक प्रविष्टि पर नामों को दोहराए बिना, यह अच्छा, कॉम्पैक्ट प्रारूप होना संभव है।

var people= new List<Tuple<int, int, string>>() {
    {1, 11, "Adam"},
    {2, 22, "Bill"},
    {3, 33, "Carol"}
}.Select(t => new { Id = t.Item1, Age = t.Item2, Name = t.Item3 });

यह एक IEnumerable देता है - यदि आप एक सूची चाहते हैं जिसे आप तब जोड़ सकते हैं तो बस ToList () जोड़ें।

मैजिक कस्टम एक्सटेंशन से आता है, tuples के लिए तरीके जोड़ें, जैसा कि https://stackoverflow.com/a/27455822/4546527 पर वर्णित है ।

public static class TupleListExtensions    {
    public static void Add<T1, T2>(this IList<Tuple<T1, T2>> list,
            T1 item1, T2 item2)       {
        list.Add(Tuple.Create(item1, item2));
    }

    public static void Add<T1, T2, T3>(this IList<Tuple<T1, T2, T3>> list,
            T1 item1, T2 item2, T3 item3) {
        list.Add(Tuple.Create(item1, item2, item3));
    }

// and so on...

}

केवल एक चीज जो मुझे पसंद नहीं है वह यह है कि प्रकार नामों से अलग किए जाते हैं, लेकिन यदि आप वास्तव में एक नया वर्ग नहीं बनाना चाहते हैं, तो यह दृष्टिकोण अभी भी आपको पढ़ने योग्य डेटा देगा।


4

मुझे बहुत आश्चर्य हुआ कि किसी ने संग्रह आरम्भिकताओं का सुझाव नहीं दिया है। यह तरीका केवल वस्तुओं को जोड़ सकता है जब सूची बनाई जाती है इसलिए नाम हालांकि यह ऐसा करने का सबसे अच्छा तरीका लगता है। कोई सरणी बनाने की आवश्यकता नहीं है, फिर उसे सूची में परिवर्तित करें।

var list = new List<dynamic>() 
{ 
    new { Id = 1, Name = "Foo" }, 
    new { Id = 2, Name = "Bar" } 
};

आप हमेशा objectइसके बजाय उपयोग कर सकते हैं dynamicलेकिन इसे एक सच्चे सामान्य तरीके से रखने की कोशिश कर रहे हैं dynamicऔर अधिक समझ में आता है।


3

आप इसे इस तरह से कर सकते हैं:

var o = new { Id = 1, Name = "Foo" };
var o1 = new { Id = 2, Name = "Bar" };

var array = new[] { o, o1 };
var list = array.ToList();

list.Add(new { Id = 3, Name = "Yeah" });

यह मेरे लिए थोड़ा "हैसी" लगता है, लेकिन यह काम करता है - अगर आपको वास्तव में एक सूची चाहिए और अनाम सरणी का उपयोग नहीं कर सकते।


3

अपने दूसरे उदाहरण के लिए, जहाँ आपको एक नया इनिशियलाइज़ करना है List<T>, एक आइडिया है एक अननोन लिस्ट बनाना और फिर उसे क्लियर करना।

var list = new[] { o, o1 }.ToList();
list.Clear();

//and you can keep adding.
while (....)
{
    ....
    list.Add(new { Id = x, Name = y });
    ....
}

या विस्तार विधि के रूप में, आसान होना चाहिए:

public static List<T> GetEmptyListOfThisType<T>(this T item)
{
    return new List<T>();
}

//so you can call:
var list = new { Id = 0, Name = "" }.GetEmptyListOfThisType();

या शायद कम,

var list = new int[0].Select(x => new { Id = 0, Name = "" }).Tolist();

2

यदि आप C # 7 या इसके बाद के संस्करण का उपयोग कर रहे हैं, तो आप गुमनाम प्रकारों के बजाय टुपल प्रकारों का उपयोग कर सकते हैं ।

var myList = new List<(int IntProp, string StrProp)>();
myList.Add((IntProp: 123, StrProp: "XYZ"));

1

इस उत्तर से व्युत्पन्न , मैं दो तरीकों के साथ आया जो कार्य कर सकते हैं:

    /// <summary>
    /// Create a list of the given anonymous class. <paramref name="definition"/> isn't called, it is only used
    /// for the needed type inference. This overload is for when you don't have an instance of the anon class
    /// and don't want to make one to make the list.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="definition"></param>
    /// <returns></returns>
#pragma warning disable RECS0154 // Parameter is never used
    public static List<T> CreateListOfAnonType<T>(Func<T> definition)
#pragma warning restore RECS0154 // Parameter is never used
    {
        return new List<T>();
    }
    /// <summary>
    /// Create a list of the given anonymous class. <paramref name="definition"/> isn't added to the list, it is
    /// only used for the needed type inference. This overload is for when you do have an instance of the anon
    /// class and don't want the compiler to waste time making a temp class to define the type.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="definition"></param>
    /// <returns></returns>
#pragma warning disable RECS0154 // Parameter is never used
    public static List<T> CreateListOfAnonType<T>(T definition)
#pragma warning restore RECS0154 // Parameter is never used
    {
        return new List<T>();
    }

आप जैसी विधियों का उपयोग कर सकते हैं

var emptyList = CreateListOfAnonType(()=>new { Id = default(int), Name = default(string) });
//or
var existingAnonInstance = new { Id = 59, Name = "Joe" };
var otherEmptyList = CreateListOfAnonType(existingAnonInstance);

इस उत्तर का एक समान विचार है, लेकिन जब तक मैंने उन तरीकों को नहीं बनाया, तब तक मैंने इसे नहीं देखा।



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