2012-04-09 11 views
61

Tengo una consulta que devuelve un tipo anónimo y la consulta está en un método. Cómo se escribe esto:Devolviendo el tipo anónimo en C#

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

     return "TheAnonymousType"; 
    } 
} 
+4

¿Por qué le gustaría devolver un tipo anónimo? ¿Cómo podría usar ese resultado en otro lugar? – Yuck

+0

posible duplicado de [¿Cómo puedo devolver un tipo anónimo desde un método?] (Http://stackoverflow.com/questions/55101/how-can-i-return-an-anonymous-type-from-a-method) – nawfal

+4

@Yuck, ¿qué pasa si estás devolviendo json o algo donde el tipo de C# no importa? – aw04

Respuesta

61

No se puede.

Solo puede devolver object, o contenedor de objetos, p. IEnumerable<object>, IList<object>, etc.

+36

O 'dynamic'. Eso hace que sea ligeramente más fácil trabajar con él. – vcsjones

+0

ah ok, entonces solo puedes usar tipos anónimos dentro de un método pero no como valores devueltos? – frenchie

+2

@frenchie: Sí, solo dentro del cuerpo del miembro. Si desea devolverlo, hágalo de un tipo conocido. – abatishchev

20

No puede devolver tipos anónimos. ¿Puedes crear un modelo que pueda devolverse? De lo contrario, debe usar un object.

Here is an article written by Jon Skeet on the subject

Código del artículo:

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

O, como otros están comentando, se puede usar dynamic

+5

Por supuesto que puedo crear un tipo; Estaba buscando evitar hacer esto. – frenchie

+0

el primer enlace está muerto, ¿no sabría si se ha transferido a otro lugar? –

+0

@ Rémi He actualizado el enlace –

1

Puede crear una lista de objetos volver en este caso .

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

     return TheQueryFromDB ; 
    } 
} 
31

Puede volver dynamic que le dará una versión de tiempo de ejecución comprobada del tipo anónimo pero sólo en .NET 4+

8

tres opciones:

Opción 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; 
    } 
} 

Opción 2:

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

se puede repetir como objeto

Opción 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 
    } 
} 

y usted será capaz de repetir como un objeto dinámico y acceder a sus propiedades directamente

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

creación de su propia clase y consultar es la mejor solución que conozco. Por mucho que sepa, no puede usar valores anónimos de devolución de tipo en otro método, porque no solo se reconocerá. Sin embargo, se pueden usar en el mismo método. Solía ​​devolverlos como IQueryable o IEnumerable, aunque todavía no le permite ver qué hay dentro de la variable de tipo anónimo.

me encuentro con algo como esto antes, mientras que yo estaba tratando de refactorizar un poco de código, puede comprobar aquí: Refactoring and creating separate methods

8

compilador de C# es un compilador de dos fases. En la primera fase solo verifica espacios de nombres, jerarquías de clases, firmas de métodos, etc. Los cuerpos de los métodos se compilan solo durante la segunda fase.

Los tipos anónimos no se determinan hasta que se compila el cuerpo del método.

Por lo tanto, el compilador no tiene forma de determinar el tipo de retorno del método durante la primera fase.

Esa es la razón por la que los tipos anónimos no se pueden usar como tipo de devolución.

Como otros han sugerido si está utilizando .net 4.0 o rallador, puede usar Dynamic.

Si yo fuera usted probablemente crearía un tipo y devolvería ese tipo del método. De esta forma, es fácil para los futuros programadores que mantienen su código y son más legibles.

16

Usted puede utilizar la clase de tupla como un sustituto de un tipo anónimo cuando regresan es necesario:

Nota: Tupla puede tener hasta 8 parámetros.

return Tuple.Create(variable1, variable2); 

O, para el ejemplo de la publicación original:

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

En C# 7 podemos usar tuplas para lograr esto:

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

Es posible que necesite para instalar System.ValueTuple nuget package though.

Cuestiones relacionadas