Domanda

Sto cercando le migliori pratiche per creare raccolte fatte da tipi anonimi.

Esistono diversi approcci: this una e più risposte su questo thread presuppone che l'intera raccolta anonima possa essere costruita in un'unica istruzione.

Poiché i tipi anonimi vengono generalmente utilizzati per sostituire le classi che devono essere utilizzate per l'archiviazione temporanea (come indicato in questa risposta SO ), vorrei evitare di creare e utilizzare una classe per raccolte anonime, come questo post suggerisce.

Nel mio caso, sto ripetendo una raccolta: per ogni elemento della raccolta vorrei raccogliere oggetti correlati in un tipo anonimo (fungendo da tupla). Ho bisogno di questi tipi anonimi per essere messi in una raccolta e poi ordinarli per ulteriori lavori.

Altri approcci che ho preso in considerazione:

  1. Utilizza un oggetto [] o ArrayList (perdendo il vantaggio del tipo anonimo)
  2. Creazione di una classe wrapper per gli elementi richiesti (eliminando la necessità del tipo anonimo)

Questo è l'unico posto nel mio codice che mi serve una tale raccolta - quale sarebbe l'approccio migliore?

Informazioni aggiuntive:

Sto lavorando con oggetti legacy .Net 1.1, quindi le raccolte con cui sto lavorando sono raccolte fortemente tipizzate che implementano IEnumerable, e come tali la maggior parte dei metodi di estensione Linq come .Select non funzionerà:

Esempio di codice

foreach (Item item in myItems)
{
    foreach (Confirmation confirmation in item.GetConfirmations(true))
    {
        if (lastParentId != item.ParentId)
        {
            lastParentId = item.ParentId;
            parentObject = new ParentItem(lastParentId);
        }

        itemHolder = new ArrayList { item, confirmation };
        if (parentObject!= null)
        {
            itemHolder.Add(parentObject.Rate);
        }

        sortConfirmations.Add(confirmation.Date, itemHolder);
    }
}

// Use sortConfirmations

Risoluzione

Ho finito per usare un dizionario generico per raccogliere insieme gli elementi correlati e usare .OrderBy () per ordinarli - brutto, ma funziona ... ed è migliore del codice esistente.

È stato utile?

Soluzione

Per una risposta molto diversa ... LINQ?

  

Nel mio caso, sto ripetendo a   raccolta - per ogni elemento in   collezione che vorrei collezionare   oggetti correlati in un tipo anonimo   (fungendo da tupla). Ho bisogno di questi   tipi anonimi da inserire a   raccolta e poi ordinarli per   ulteriori lavori.

Sembra:

var list = (from item in collection
          from related in item.Relationship
          order by ...something...
          select new {item,related}).ToList()

Altri suggerimenti

Se sei soddisfatto di un array, puoi utilizzare un inizializzatore di array:

var items = new[] {
    new { Foo = "def" },
    new { Foo = "ghi" },
    new { Foo = "jkl" }
};

È quindi possibile chiamare ToList() se si desidera ottenere un List<T>. La soluzione di Marc sarà leggermente più efficiente rispetto alla chiamata di Select a causa della non necessità della copia aggiuntiva, ma penso probabilmente userò l'array & Quot; e quindi ToList () " soluzione nella maggior parte dei casi in quanto c'è meno disordine. Naturalmente, se le prestazioni sono cruciali per quel pezzetto di codice, cambiano le cose.

MODIFICA: mentre stai iterando su una raccolta, usa <=>:

var anonymousItems = items.Select (item => new { Foo=item.Foo, 
                                                 Bar=item.Other })
                          .ToList();

Un'opzione è utilizzare un elemento di esempio per creare la raccolta tramite inferenza di tipo generico, ad esempio:

    static List<T> CreateEmptyList<T>(T template) {
        return new List<T>();
    }
    void Foo() {
        var list = CreateEmptyList(new { Foo = "abc" });
        list.Add(new { Foo = "def" });
        //...
    }

Puoi anche farlo senza creare un'istanza (ma usando un metodo anonimo che non ottiene mai il chiamante), ma non penso che salvi nulla in realtà ... potremmo non creare un'istanza dell'oggetto, ma creiamo un'istanza di un delegato, quindi non molto di un risparmio ...

Si menziona anche l'ordinamento dei dati; vedi la rispondi qui per un modo per usa List<T>.Sort con un lambda, e quindi con tipi anonimi - cioè

list.Sort(x=>x.Foo);

LINQ è la strada da percorrere. Supponendo di voler recuperare gli oggetti correlati A, B e C di ogni elemento in un insieme di oggetti e ordinare in base all'oggetto correlato A, si procederà come segue.

var relatedObjects = items.
       Select(item => new { A = item.A, B = item.B, C = item.C } ).
       OrderBy(item => item.A);

Ottieni una raccolta di elementi di tipo anonimo con le tre proprietà A, B e C impostate sugli oggetti correlati ordinati dall'oggetto correlato A.

Non l'ho verificato, ma dovresti essere in grado di estendere la raccolta RelatedObject in un secondo momento. Basta fare quanto segue per aggiungere un singolo nuovo elemento. Questo dovrebbe funzionare perché esiste un solo tipo anonimo per assembly, penso che se i nomi e i tipi di ciascuna proprietà corrispondono.

relatedObjects = relatedObjects.Union(
   Enumerable.Repeat(new { A = someA, B = someB, C = someC }, 1))

Abbastanza brutto a causa dell'Enumerable.Repeat () ma diventa abbastanza bello se ti unisci con una raccolta di nuovi oggetti invece di un singolo nuovo oggetto.

Mi sono imbattuto in questa domanda mentre cercavo un modo per creare un elenco temporaneo di oggetti temporanei. Perché dovrei voler creare una cosa del genere? Stavo cercando un modo rapido per restituire JSON per un elenco di oggetti creati da alcuni valori di un altro oggetto. Ecco cosa intendo.

Supponiamo di avere una classe Employee sul lato server che assomigli a quanto segue in C #:

public class Employee
{
          public int Id;
       public int businessGroupId;
       public string title;
       public int positionId;

       public string firstName;
       public string lastName;
       ...
}

Inoltre ho una raccolta di quegli oggetti che posso facilmente scorrere, qualcosa come il seguente:

List<Employee> allEmployees  = new List<Employee>();

Ora, voglio tornare alla mia pagina Web chiamante l'intera raccolta di dipendenti , ma voglio solo il nome, il cognome per ciascuno . Li voglio restituiti come JSON.

Ecco il punto importante

Non voglio restituire tutte le proprietà nell'oggetto Employee.

So di poter facilmente creare un tipo anonimo ripetendo la raccolta allEmployees e costruendo ogni volta un nuovo oggetto.

Sarebbe simile al seguente:

foreach (Employee e in allEmployees)
{
    var tempObj = new {F_Name=e.firstName, L_Name=e.lastName};
}

Qual è il tipo di un tipo anonimo? :)

Il trucco ora è che voglio un'intera collezione (Lista < >) di questi oggetti anonimi. Tuttavia, non ho modo di fornire all'Elenco un tipo che userò. Non riesco a creare un  List<unknown> allTempObjects = new List<unknown>();

O posso?

Con dinamico, è possibile

Posso fare quanto segue e funziona benissimo:

List<dynamic> allEmployees  = new List<dynamic>();

foreach (Employee e in allEmployees)
{
           var tempObj = new {F_Name=e.firstName, L_Name=e.lastName};
        allEmployees.Add(tempObj);
}

// use the JavaScript Serializer to serialize the dynamic collection
JavaScriptSerializer jss = new JavaScriptSerializer();
// write the result out to the HTTP Stream (HtmlTextWriter in overridden Render method)

 writer.Write(jss.Serialize(allEmployees));

Vedrai JSON sul lato client che è simile al seguente:

[
    {
      F_Name: "Seth",
      L_Name: "Godin"
    },
    {
       F_Name: "Charles",
       L_Name: "Petzold"
    },
    {
       F_Name: "Jeff",
       L_Name: "Prosise"
    }
]

Infine, potresti chiederti perché voglio farlo. La semplice risposta è che voglio un nuovo tipo che viene utilizzato solo per serializzare per inviare al mio client. Un ottimo motivo per un tipo anonimo e una raccolta anonima di tipi anonimi, non credi?

  

questo e la maggior parte delle risposte su questo   il thread presuppone che l'intero anonimo   la raccolta può essere costruita in uno   comunicato.

Sì, in genere crei una raccolta di tipo anonimo in una singola istruzione. Se hai bisogno di più dichiarazioni, potresti finire con una raccolta piuttosto inutile di diversi tipi anonimi.

I tipi anonimi sono utili quando li crei in una singola istruzione e li usi subito. Se la creazione della raccolta o l'ulteriore elaborazione è un po 'più complessa, il tipo anonimo perde parte della sua utilità. Ad esempio, non è possibile passare in modo efficiente un tipo anonimo a un metodo per l'elaborazione, poiché il metodo non conosce il tipo di oggetto e quindi deve utilizzare la riflessione per estrarre qualcosa da esso.

Se stai cercando ripetutamente elementi in questa raccolta di tipi anonimi, potresti voler creare un tipo denominato in modo da poterli inserire in un dizionario per una ricerca molto più veloce.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top