Как вернуть анонимный тип при использовании Linq

Возможный дубликат:
LINQ to SQL: возврат анонимного типа ?

Кто-нибудь знает, как вернуть анонимный тип. Я использую Linq, где мне нужно вернуть следующий код

private <What's the return type to be provided here> SampleLinq(Int32 Num)
    {
        var query = (from dept in obj.DeptTable where dept.Id == Num select new { dept.DeptName, dept.DeptId });
        return (query)       

    }

person user403320    schedule 30.06.2010    source источник
comment
Дуп: stackoverflow.com/questions/1070526/   -  person Krunal    schedule 30.06.2010
comment
@Krunal - тот закрыт как дубликат того, который я использовал.   -  person ChrisF    schedule 30.06.2010
comment
@ChrisF - Ага, знай это. но пусть OP все видит.   -  person Krunal    schedule 30.06.2010


Ответы (8)


К сожалению, вы не можете вернуть анонимный тип вне области действия метода.

Это альтернативный способ получить анонимный тип

// Method that returns anonymous type as object
object ReturnAnonymous()
{
  return new { City="Prague", Name="Tomas" };
}

// Application entry-point
void Main()
{
  // Get instance of anonymous type with 'City' and 'Name' properties
  object o = ReturnAnonymous();

  // This call to 'Cast' method converts first parameter (object) to the
  // same type as the type of second parameter - which is in this case 
  // anonymous type with 'City' and 'Name' properties
  var typed = Cast(o, new { City="", Name="" });
  Console.WriteLine("Name={0}, City={1}", typed.Name, typed.City);
}

// Cast method - thanks to type inference when calling methods it 
// is possible to cast object to type without knowing the type name
T Cast<T>(object obj, T type)
{
  return (T)obj;
}

вы можете использовать его только для типов в одной сборке (два анонимных типа из двух разных сборок будут внутренне скомпилированы в два разных типа, которые нельзя преобразовать с помощью этого трюка).

person Pranay Rana    schedule 30.06.2010

Вернуть динамический тип:

      public static dynamic  getCustomer() 
{ 
    ..... 
    var x = from c in customers 
            select new {Fname = c.FirstName}; 

    return x; 
} 

static void Main(string[] args) 
{ 
    dynamic x = getCustomer(); 
    Console.WriteLine(Enumerable.First(x).Fname); 
    Console.ReadKey(); 
} 
person Stacker    schedule 02.08.2010

ты не можешь этого сделать. поэтому его называют анонимным. У него нет названия. Но вы всегда можете преобразовать его в object

person Andrey    schedule 30.06.2010

На самом деле вы не можете этого сделать, но вот хак по этому поводу.

person this. __curious_geek    schedule 30.06.2010
comment
Лучше было бы хотя бы добавить краткое описание взлома на случай, если ссылка, которую вы предлагаете, не работает. - person jpierson; 12.04.2011

Вы не можете вернуть анонимный тип из метода.

Вы можете создать простой класс для обертывания анонимного типа, но вам все равно понадобится класс (или приведение к object).

Однако имейте в виду, что если вы приведете к object, нет возможности выполнить обратное преобразование. Для чтения любых данных вам понадобится отражение.

person Justin Niessner    schedule 30.06.2010

Ответы, которые вы увидите после взлома, - это большая работа, чтобы просто получить анонимный тип через границу метода. Тебе не следует этого делать. Если вам нужно передать что-то из метода, вы должны передавать конкретные типы.

person Matthew Abbott    schedule 02.08.2010
comment
@Mathew - В общем, я был бы с вами согласен, но в случаях привязки данных целевое свойство (например, DataContext) в любом случае является просто типовым объектом, и привязка на самом деле не привязана до времени выполнения. Так, например, может быть полезно вернуть IEnumerable, который перечисляет экземпляры анонимного типа, которые действуют как оболочки / модели просмотра только для чтения для данной коллекции. Поэтому в некоторых случаях я думаю, что имеет смысл разрешить возвращать экземпляры анонимного типа. - person jpierson; 12.04.2011
comment
@jpierson - Конечно, я думаю, что всегда есть исключения из правил. Я надеюсь, что в данном случае это может быть один из таких случаев, но в ситуациях, когда вы пытаетесь получить доступ к этим членам в коде, пора переключиться с анонимных экземпляров на статически типизированные. - person Matthew Abbott; 12.04.2011
comment
@Mathew - Согласен, например, когда вы используете отражение в коде только для получения значений. Вероятно, существует небольшой набор примеров, где это могло бы быть законным, но в противном случае вы действительно пытаетесь выполнять динамическое программирование на статически типизированном языке. Теперь с помощью ключевого слова dynamic я могу видеть, где некоторые разработчики C # могут начать проявлять некоторую эксцентричность в использовании программирования в динамических стилях, но его превышение быстро становится ненужным отклонением от преимуществ использования строго типизированного языка, такого как C #. - person jpierson; 14.04.2011

Это зависит от того, что вы собираетесь делать с долей возврата.

  • Если вы собираетесь привязать его в пользовательском интерфейсе, вы можете просто повторно запустить IEnumerable или IQueryable.

  • Если вы собираетесь использовать отражение в возвращаемом значении, просто верните объект типа

  • Если вы используете С # 4.0, вы можете вернуть динамический тип

  • Если вы используете EF или Linq to SQL для дальнейшего присоединения к запросу, состоящему из вашего анонимного типа, вы можете вместо этого создать конкретный класс и использовать технику конкретного заполнителя. Для получения более подробной информации об этой технике я могу оказать некоторую помощь.

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

ОБНОВЛЕНИЕ: просто интересный лакомый кусочек, которым я хотел бы поделиться на случай, если читающие не знают. Анонимные типы уникальны по их именам свойств и типам, поэтому допустим, что у вас есть метод A и метод B, в обоих случаях вы создаете анонимный тип, который имеет свойство типа одной строки с именем Name, выполняя что-то вроде кода be ниже.

public object A()
{
    return new { Name = "Cid" }
}

public object B()
{
    return new { Name = "Galuf" }
}

public void Test()
{
   System.Diagnostics.Trace.Assert(A().GetType() == B().GetType());
}

Теперь, несмотря на то, что этот тип определен в двух разных местах, компилятор создает только один общий тип, потому что они оба имеют одинаковый набор свойств, как определено типами свойств и именами свойств. В этом отношении свойства можно рассматривать как своего рода сигнатуру анонимного типа. Используя эти знания, существуют различные методы, которые можно использовать для самоанализа в экземпляры анонимного типа, которые были преобразованы в объект или отложены с использованием ключевого слова dynamic. Есть также изящные способы работы с анонимными типами с помощью универсальных методов, точно так же, как Linq делает с методами в статических классах Enumerable и Queryable. Таким образом, вы можете делать такие вещи, как создание нового экземпляра любого анонимного типа без использования отражения. Уловка заключается в том, что вы должны использовать экземпляр анонимного типа для передачи методам, чтобы тип был выведен универсальным методом. Если кого-то интересуют эти темы, поскольку они применимы к исходному вопросу плаката, оставьте комментарий, и я могу попытаться прояснить некоторые из этих методов.

person jpierson    schedule 03.07.2010
comment
В самом деле! Нет комментариев, чтобы объяснить отрицательные голоса? - person jpierson; 12.04.2011
comment
+1 Я никогда не знал, что эти типы могут быть равными! Голос против может быть из-за вашего The trick is though that you have to use an instance of the anonymous type to pass to methods in order to have the type be inferred by the generic method. If anybody is interested in these topics further as they apply to the original posters question, leave a comment and I can try to clarify some of these techniques., а не из-за того, что вы не написали, что это такое. - person nawfal; 04.02.2013

person    schedule
comment
но как повторно преобразовать объект в var, чтобы получить свойства, поскольку объект не содержит общедоступного определения для getenumerator? - person user403320; 30.06.2010
comment
Без дополнительных указаний, таких как FirstOrDefault (), запрос вернет IEnumerable ‹›. И затем вам нужно использовать Reflection, чтобы понять, как его использовать. - person GalacticCowboy; 30.06.2010
comment
@renjithmaxy - var! = ‹мой анонимный тип›. var все еще строго типизирован во время компиляции. - person GalacticCowboy; 30.06.2010