将匿名类型的对象作为参数传递给方法

5
我需要做类似以下的事情:
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)
}

我需要将queryResult变量传递给函数doSomething()。我尝试使用动态类型List<T>对象,但没有任何效果。

public void doSomething(???? queryResult)
{
    foreach (carros ca in queryResult)
    {
        Response.Write(ca.nome);
        Response.Write(" - ");
        Response.Write(ca.id);
    }
}

1
在Visual Studio中,您可以将鼠标悬停在“var”关键字上以查看生成结果的类型。 - lukegravitt
4个回答

11

通常情况下,将匿名类型在方法之间传递几乎总是一个不好的想法。

你应该创建一个自定义类型来保存nomeid的值,然后构造它而不是使用匿名类型。


在你的情况下,你已经有一个可用的类:carros。你可以实现查询以创建它:

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

你的方法将会是:

public void doSomething(IEnumerable<carros> queryResults)

你能解释一下为什么这是一个不好的主意吗?他已经有一个叫做Carros的对象,其中包含nomeid属性。 - Itanex
3
这个想法不好的原因是你创建的匿名类型是匿名的。也就是说,除了在它被用于LINQ查询时(或者使用反射技巧)之外,没有其他方法来构造它。尽管匿名类型很有帮助,但它们的范围确实应该被限制在初始方法中。如果你想要传递它们,那么显然它们具有超出初始范围的相关性,因此,它们值得拥有一个名称和声明。 - Andrew Coonce
代码 select new carros {q.nome, q.id}; 中的 new 关键字出现错误,错误提示为:Error 3 'testeLINQ.carros' does not contain a constructor that takes 0 arguments。 - Felipe Maricato Moura
@FelipeMaricatoMoura 问题在于您没有展示出 carros 类 - 您发布的代码应该有一个默认构造函数。根据您的类定义方式,您可能需要使用 select new carros(q.nome, q.id) 或类似的方法。 - Reed Copsey

3

关于传递匿名类型,虽然有人提到传递匿名类型是不好的选择,但如果你真的想这么做(利用动态语言),你仍然可以这样做。

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

     AnonReciever(x);
}

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

这将毫无问题地打印出bar

不过我不建议这样做。最好使用自定义类型的对象,你已经拥有了它。


无法工作的动态显示错误:“找不到命名空间dynamic”。 - Felipe Maricato Moura

2

您不能在当前方法的范围之外传递匿名类型*。请使用您的carros类型:

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

* 您只能将它们作为一个对象传递,这几乎没有用处,因为您想以强类型方式使用它们。


抱歉,使用“select q”可以正常工作;但是对于“select new carros {q.nome, q.id}”或“select new {q.nome, q.id}”则无法工作。你知道为什么吗? - Felipe Maricato Moura
@FelipeMaricatoMoura:所以你改变了示例代码,然后抱怨你的更改有一个错误(而原始代码没有)? - Andrew Coonce
代码 select new carros {q.nome, q.id}; 中的 new 关键字出现错误。 错误信息:Error 3 'testeLINQ.carros' 不包含不带参数的构造函数。 - Felipe Maricato Moura

2
为什么不将新对象声明为carros类型?
var qry = from q in Lcars 
          where q.nome.ToLower().Contains("eco") 
          orderby q.nome 
          select new carros {q.nome, q.id};

你的参数将会:

 IEnumerable{carros}

错误:错误 3 'testeLINQ.carros' 不包含不带参数的构造函数。 - Felipe Maricato Moura

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接