5

I need do something like this:

public class carros 
{
    public int id { get; set; }
    public string nome { get; set; }
}

public void listar_carros()
{
    List<carros> cars = new List<carros>();
    cars.Add(new carros{ id= 1, nome = "Fusca" });
    cars.Add(new carros{ id= 2, nome = "Gol" });
    cars.Add(new carros{ id= 3, nome = "Fiesta" });

    var queryResult = from q in cars 
                      where q.nome.ToLower().Contains("eco") 
                      orderby q.nome 
                      select new { q.nome, q.id };

    doSomething(queryResult)
}

I need to pass the queryResult variable to function doSomething(). I tried use a dynamic type, List<T> object, but nothing works

public void doSomething(???? queryResult)
{
    foreach (carros ca in queryResult)
    {
        Response.Write(ca.nome);
        Response.Write(" - ");
        Response.Write(ca.id);
    }
}
davmos
  • 9,324
  • 4
  • 40
  • 43

4 Answers4

11

In general, it's almost always a bad idea to pass anonymous types between methods.

You should make a custom type to hold the nome and id values, then construct it instead of an anonymous type.


In your case, you already have a class that would work: carros. You can just implement your query to create it instead:

var queryResult = from q in cars 
  where q.nome.ToLower().Contains("eco") 
  orderby q.nome 
  select new carros {q.nome, q.id};

Your method would then be:

public void doSomething(IEnumerable<carros> queryResults)
Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • Can you explain why this is a bad idea? He has an object already called `Carros` which has `nome` and `id` – Itanex Aug 19 '13 at 21:48
  • 3
    @FelipeMaricatoMoura: The reason it's a bad idea is because the anonymous type that you've created is *anonymous*. That is: there's no way to construct it outside of the LINQ query where it was used (outside of reflection hackery). As helpful as anonymous types are, they are rightfully limited in scope to their initial method. If you want to pass them, they clearly have relevance beyond that initial scope and thus, are deserving of a name and a declaration. – Andrew Coonce Aug 19 '13 at 22:27
  • error show on word new in code select new carros {q.nome, q.id}; erro: Error 3 'testeLINQ.carros' does not contain a constructor that takes 0 arguments – – Felipe Maricato Moura Aug 19 '13 at 23:08
  • @FelipeMaricatoMoura The problem is that you're not showing your `carros` class - the code you posted would have a default constructor. You may need to use `select new carros(q.nome, q.id)` or similar, depending on how your class is actually defined. – Reed Copsey Aug 19 '13 at 23:21
3

Just wanted to chime in regarding passing anonymous types, while it's been mentioned that its bad juju to pass anonmyous types, you can... if you really wanted to (leveraging dynamic)

public void Anon()
{
     var x = new {foo = "bar"};

     AnonReciever(x);
}

public static void AnonReciever(dynamic o)
{
     Console.WriteLine(o.foo);
}

And this prints bar no problem.

I don't recommend it though. Best to use a custom typed object, which you already have.

devshorts
  • 8,572
  • 4
  • 50
  • 73
2

You cannot pass anonymous types* outside the scope of the current method. Use your carros type:

public void listar_carros()
{
    List<carros> Lcars = new List<carros>();
    Lcars.Add(new carros(1, "Fusca"));
    Lcars.Add(new carros(2, "Gol"));
    Lcars.Add(new carros(3, "Fiesta"));

    var qry = from q in Lcars
              where q.nome.ToLower().Contains("eco")
              orderby q.nome
              select q;

    doSomething(qry);

}

public void doSomething(IEnumerable<carros> qry)
{

    foreach (carros ca in qry)
    {
        Response.Write(ca.nome);
        Response.Write(" - ");
        Response.Write(ca.id);
        //Response.Write(ca);
        Response.Write("<br />");
    }
}

* You can pass them only as an object which is mostly useless since you would want to use them in strong-typed way.

Magnus
  • 45,362
  • 8
  • 80
  • 118
Ed Chapel
  • 6,842
  • 3
  • 30
  • 44
  • sorry works fine using a selec q; but not work for select new carros {q.nome, q.id}; or select new {q.nome, q.id}; do you know what? – Felipe Maricato Moura Aug 19 '13 at 22:12
  • @FelipeMaricatoMoura: So you changed the presented code example and then complained that your change has a bug (when the original code didn't)? – Andrew Coonce Aug 19 '13 at 22:28
  • error show on word new in code select new carros {q.nome, q.id}; erro: Error 3 'testeLINQ.carros' does not contain a constructor that takes 0 arguments – – Felipe Maricato Moura Aug 19 '13 at 23:09
2

Why not declare the new object as type carros?

var qry = from q in Lcars 
          where q.nome.ToLower().Contains("eco") 
          orderby q.nome 
          select new carros {q.nome, q.id};

Your parameter would then:

 IEnumerable{carros}
Magnus
  • 45,362
  • 8
  • 80
  • 118
ChargerIIC
  • 1,620
  • 1
  • 33
  • 47