Возврат анонимного типа В C#


У меня есть запрос, который возвращает анонимный тип и запрос в метод. Как вы пишете это:

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

      return "TheAnonymousType";
    }
}
10 74

10 ответов:

ты не можешь.

вы можете только вернуть object, или контейнер объектов, например,IEnumerable<object>,IList<object> и т. д.

вы можете вернуть dynamic Что даст вам проверенную во время выполнения версию анонимного типа, но только в .NET 4+

вы не можете вернуть анонимные типы. Вы можете создать модель, которая может быть возвращена? В противном случае, вы должны использовать object.

вот статья, написанная Джоном скитом на эту тему

код из статьи:

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

Или вот еще одна подобная статья

или, как другие комментируют, вы могли бы использовать dynamic

вы можете использовать класс кортежа в качестве замены анонимных типов при необходимости возврата:

Примечание: Кортеж может иметь до 8 параметров.

return Tuple.Create(variable1, variable2);

или, например, из исходного поста:

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

компилятор C# является двухфазным компилятором. На первом этапе он просто проверяет пространства имен, иерархии классов, сигнатуры методов и т. д. Тела методов компилируются только на втором этапе.

анонимные типы не определяются до тех пор, пока не будет скомпилировано тело метода.

таким образом, компилятор не имеет возможности определить тип возвращаемого метода на первом этапе.

вот почему анонимные типы не могут быть использованы в качестве возврата тип.

как другие предложили, если вы используете .net 4.0 или терку, вы можете использовать Dynamic.

на вашем месте я бы, вероятно, создал тип и вернул этот тип из метода. Таким образом, это легко для будущих программистов, которые поддерживают ваш код и более читаемым.

три варианта:

Option1:

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

Вариант 2:

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

вы можете повторить его как объекта

Вариант 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
   } 
}

и вы сможете повторить его как динамический объект и получить доступ к их свойствам напрямую

В C# 7 мы можем использовать кортежи для этого:

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

возможно, Вам потребуется установить System.ValueTuple пакет nuget, хотя.

вы можете вернуть список объектов в этом случае.

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

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

создание собственного класса и запрос на него-лучшее решение I know.As насколько я знаю, вы не можете использовать возвращаемые значения анонимного типа в другом методе, потому что он не будет просто распознан.Тем не менее, они могут быть использованы в том же методе. Я привык возвращать их как IQueryable или IEnumerable, хотя он по-прежнему не позволяет увидеть, что находится внутри переменной анонимного типа.

я столкнулся с чем-то вроде этого раньше, когда я пытался рефакторинг какой-то код, вы можете проверить это здесь : рефакторинг и создание отдельных методов

вы можете использовать ключевое слово 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};
   }

но с ключевым словом динамического типа Вы потеряете безопасность времени компиляции, IDE IntelliSense и т. д...