Restituzione di tipo anonimo in C #

Ho una query che restituisce un tipo anonimo e la query è in un metodo. Come scrivi questo:

public "TheAnonymousType" TheMethod(SomeParameter) { using (MyDC TheDC = new MyDC()) { var TheQueryFromDB = (.... select new { SomeVariable = ...., AnotherVariable = ....} ).ToList(); return "TheAnonymousType"; } } 

Non puoi

È ansible restituire solo object o contenitore di oggetti, ad esempio IEnumerable , IList , ecc.

Puoi tornare dynamic che ti darà una versione controllata in runtime del tipo anonimo ma solo in .NET 4+

Non è ansible restituire tipi anonimi. Puoi creare un modello che può essere restituito? Altrimenti, devi usare un object .

Ecco un articolo scritto da Jon Skeet sull’argomento

Codice dall’articolo:

 using System; static class GrottyHacks { internal static T Cast(object target, T example) { return (T) target; } } class CheesecakeFactory { static object CreateCheesecake() { return new { Fruit="Strawberry", Topping="Chocolate" }; } static void Main() { object weaklyTyped = CreateCheesecake(); var stronglyTyped = GrottyHacks.Cast(weaklyTyped, new { Fruit="", Topping="" }); Console.WriteLine("Cheesecake: {0} ({1})", stronglyTyped.Fruit, stronglyTyped.Topping); } } 

O, ecco un altro articolo simile

Oppure, come altri stanno commentando, potresti usare la dynamic

È ansible utilizzare la class Tuple come sostituto di un tipo anonimo quando è necessario restituire:

Nota: Tuple può avere fino a 8 parametri.

 return Tuple.Create(variable1, variable2); 

Oppure, per l’esempio del post originale:

 public List> TheMethod(SomeParameter) { using (MyDC TheDC = new MyDC()) { var TheQueryFromDB = (.... select Tuple.Create(..., ...) ).ToList(); return TheQueryFromDB.ToList(); } } 

http://msdn.microsoft.com/en-us/library/system.tuple(v=vs.110).aspx

Il compilatore C # è un compilatore a due fasi. Nella prima fase controlla solo gli spazi dei nomi, le gerarchie delle classi, le firme dei metodi, ecc. I corpi dei metodi vengono compilati solo durante la seconda fase.

I tipi anonimi non vengono determinati fino a quando il corpo del metodo non viene compilato.

Quindi il compilatore non ha modo di determinare il tipo di ritorno del metodo durante la prima fase.

Questo è il motivo per cui i tipi anonimi non possono essere usati come tipo di ritorno.

Come altri hanno suggerito se stai usando .net 4.0 o grater, puoi usare Dynamic .

Se fossi in te probabilmente creerei un tipo e restituirò quel tipo dal metodo. In questo modo è facile per i futuri programmatori che mantengono il tuo codice e sono più leggibili.

Tre opzioni:

Opzione 1:

 public class TheRepresentativeType { public ... SomeVariable {get;set;} public ... AnotherVariable {get;set;} } public IEnumerable TheMethod(SomeParameter) { using (MyDC TheDC = new MyDC()) { var TheQueryFromDB = (.... select new TheRepresentativeType{ SomeVariable = ...., AnotherVariable = ....} ).ToList(); return TheQueryFromDB; } } 

Opzione 2:

 public IEnumerable TheMethod(SomeParameter) { using (MyDC TheDC = new MyDC()) { var TheQueryFromDB = (.... select new TheRepresentativeType{ SomeVariable = ...., AnotherVariable = ....} ).ToList(); return TheQueryFromDB; } } 

puoi iterarlo come object

Opzione 3:

 public IEnumerable TheMethod(SomeParameter) { using (MyDC TheDC = new MyDC()) { var TheQueryFromDB = (.... select new TheRepresentativeType{ SomeVariable = ...., AnotherVariable = ....} ).ToList(); return TheQueryFromDB; //You may need to call .Cast(), but I'm not sure } } 

e sarete in grado di iterarlo come un object dinamico e accedere direttamente alle loro proprietà

In C # 7 possiamo usare le tuple per realizzare questo:

 public List<(int SomeVariable, string AnotherVariable)> TheMethod(SomeParameter) { using (MyDC TheDC = new MyDC()) { var TheQueryFromDB = (.... select new { SomeVariable = ...., AnotherVariable = ....} ).ToList(); return TheQueryFromDB.Select(s => (SomeVariable = s.SomeVariable, AnotherVariable = s.AnotherVariable)).ToList(); } } 

Potrebbe essere necessario installare il pacchetto nuget System.ValueTuple .

In questo caso è ansible restituire l’elenco degli oggetti.

 public List TheMethod(SomeParameter) { using (MyDC TheDC = new MyDC()) { var TheQueryFromDB = (.... select new { SomeVariable = ...., AnotherVariable = ....} ).ToList(); return TheQueryFromDB ; } } 
 public List TheMethod(SomeParameter) { using (MyDC TheDC = new MyDC()) { var TheQueryFromDB = (.... select new SomeClass{ SomeVariable = ...., AnotherVariable = ....} ).ToList(); return TheQueryFromDB.ToList(); } } public class SomeClass{ public string SomeVariable{get;set} public string AnotherVariable{get;set;} } 

Creare la tua class e interrogare per questo è la soluzione migliore che conosca. Poiché so che non puoi usare valori di ritorno di tipo anonimo in un altro metodo, perché non sarà solo riconosciuto. Tuttavia, possono essere usati nello stesso metodo. Ho usato restituirli come IQueryable o IEnumerable , anche se ancora non ti permette di vedere cosa c’è dentro la variabile di tipo anonimo.

Mi sono imbattuto in qualcosa di simile prima mentre cercavo di refactoring del codice, puoi verificarlo qui: Refactoring e creazione di metodi separati

Puoi utilizzare solo la parola chiave dynamic,

  dynamic obj = GetAnonymousType(); Console.WriteLine(obj.Name); Console.WriteLine(obj.LastName); Console.WriteLine(obj.Age); public static dynamic GetAnonymousType() { return new { Name = "John", LastName = "Smith", Age=42}; } 

Ma con la parola chiave di tipo dinamico perderai la sicurezza della compilazione, IDE IntelliSense ecc …