2012-04-09 15 views
61

Mam kwerendę, która zwraca typ anonimowy i kwerenda jest w metodzie. Jak to piszesz:Zwracanie anonimowego typu w języku C#

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

     return "TheAnonymousType"; 
    } 
} 
+4

Dlaczego chcesz zwrócić anonimowy typ? Jak mógłbyś wykorzystać ten wynik w innym miejscu? – Yuck

+0

możliwy duplikat [Jak mogę zwrócić anonimowy typ z metody?] (Http://stackoverflow.com/questions/55101/how-can-i-return-an-anonymous-type-od-a-ethod) – nawfal

+4

@ Co jeśli powracasz json lub coś, w którym typ C# nie ma znaczenia – aw04

Odpowiedz

61

Nie możesz.

Możesz tylko zwrócić object, lub kontener obiektów, np. IEnumerable<object>, IList<object>, itp.

+36

Lub 'dynamic'. To sprawia, że ​​praca z nim jest nieco łatwiejsza. – vcsjones

+0

ah ok, więc możesz używać tylko typów anonimowych w metodzie, ale nie jako wartości zwracanych? – frenchie

+2

@frenchie: Tak, tylko wewnątrz ciała członka. Jeśli chcesz go zwrócić - uczyń go znanym typem. – abatishchev

20

Nie można zwrócić anonimowych typów. Czy możesz stworzyć model, który można zwrócić? W przeciwnym razie musisz użyć numeru object.

Here is an article written by Jon Skeet on the subject

Kod z artykułu:

using System; 

static class GrottyHacks 
{ 
    internal static T Cast<T>(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);    
    } 
} 

Or, here is another similar article

Albo, jak inni komentują, można użyć dynamic

+5

Oczywiście mogę utworzyć typ; Chciałem tego uniknąć. – frenchie

+0

pierwszy link jest martwy, czy przypadkiem nie wiesz, czy został przeniesiony gdzie indziej? –

+0

@ Remi zaktualizowałem link –

1

Można listę obiektów wrócić w tym przypadku .

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

     return TheQueryFromDB ; 
    } 
} 
31

Możesz powrócić dynamic który daje wykonania sprawdzone wersję anonimowego typu, ale tylko w .NET 4+

8

trzy opcje:

Opcja 1:

public class TheRepresentativeType { 
    public ... SomeVariable {get;set;} 
    public ... AnotherVariable {get;set;} 
} 

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

    return TheQueryFromDB; 
    } 
} 

Opcja 2:

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

można iteracyjne go jako obiektu

Wariant 3:

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

    return TheQueryFromDB; //You may need to call .Cast<dynamic>(), but I'm not sure 
    } 
} 

i będzie można iteracyjne go jako obiekt dynamiczny i dostęp do ich właściwości bezpośrednio

2
public List<SomeClass> 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;} 
} 

tworzenia własnych klasę i sprawdzanie, czy jest to najlepsze rozwiązanie, jakie znam. O ile wiem, nie można użyć wartości zwracanych w anonimowym typie w innej metodzie, ponieważ nie będzie ona tylko rozpoznawana. Można je jednak zastosować w tej samej metodzie. Kiedyś zwracałem je jako IQueryable lub IEnumerable, ale nadal nie pozwala zobaczyć, co jest wewnątrz anonimowej zmiennej typu.

biegnę do czegoś takiego wcześniej, a ja starałem byłaby trochę kodu, można to sprawdzić tutaj: Refactoring and creating separate methods

8

kompilator C# kompilator jest dwufazowy. W pierwszej fazie sprawdza tylko przestrzenie nazw, hierarchie klas, podpisy metod itp. Ciała metod są kompilowane tylko podczas drugiej fazy.

Typy anonimowe nie są określane, dopóki treść metody nie zostanie skompilowana.

Tak więc kompilator nie ma możliwości określenia typu powrotu metody podczas pierwszej fazy.

To jest powód, dla którego typy anonimowe nie mogą być używane jako typ zwracany.

Inni sugerują, że jeśli używasz .net 4.0 lub tarka, możesz użyć Dynamic.

Gdybym był tobą, prawdopodobnie utworzyłbym typ i zwrócę ten typ z metody. W ten sposób przyszli programiści, którzy utrzymają twój kod i będą bardziej czytelni, będą mogli łatwo.

16

Można użyć klasy krotka jako substytut dla anonimowych typów po powrocie jest konieczne:

Uwaga: Tuple może mieć maksymalnie 8 parametrów.

return Tuple.Create(variable1, variable2); 

Albo na przykład z oryginalnego postu:

public List<Tuple<SomeType, AnotherType>> 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

4

W języku C# 7 możemy użyć krotki do osiągnięcia tego celu:

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(); 
    } 
} 

może być konieczne zainstalować pakiet nuget System.ValueTuple.

Powiązane problemy