如何传递匿名types作为参数?

我如何将匿名types作为parameter passing给其他函数? 考虑这个例子:

var query = from employee in employees select new { Name = employee.Name, Id = employee.Id }; LogEmployees(query); 

这里的variablesquery没有强types。 我应该如何定义我的LogEmployees函数来接受它?

 public void LogEmployees (? list) { foreach (? item in list) { } } 

换句话说,我应该用什么来代替? 分数。

我想你应该为这个匿名types做一个类。 在我看来,这是最明智的做法。 但是,如果你真的不想,你可以使用dynamic:

 public void LogEmployees (IEnumerable<dynamic> list) { foreach (dynamic item in list) { string name = item.Name; int id = item.Id; } } 

请注意,这不是强types的,所以如果Name更改为EmployeeName,则直到运行时才会知道存在问题。

你可以这样做:

 public void LogEmployees<T>(List<T> list) // Or IEnumerable<T> list { foreach (T item in list) { } } 

…但是你不会对每个项目做很多事情。 你可以调用ToString,但是你将无法直接使用(比如说) NameId

不幸的是,你想要做的是不可能的。 在底层,查询variables被键入为一个匿名types的IEnumerable。 匿名types名称不能在用户代码中表示,因此没有办法使它们成为函数的input参数。

最好的办法是创build一个types,并将其用作查询的返回,然后将其传递给函数。 例如,

 struct Data { public string ColumnName; } var query = (from name in some.Table select new Data { ColumnName = name }); MethodOp(query); ... MethodOp(IEnumerable<Data> enumerable); 

在这种情况下,您只是select一个字段,所以直接select字段可能会更容易一些。 这将导致查询被input为字段types的IEnumerable。 在这种情况下,列名称。

 var query = (from name in some.Table select name); // IEnumerable<string> 

除非参数types是object ,否则不能将匿名types传递给非generics函数。

 public void LogEmployees (object obj) { var list = obj as IEnumerable(); if (list == null) return; foreach (var item in list) { } } 

匿名types用于方法中的短期使用。

来自MSDN – 匿名types :

您不能将方法的字段,属性,事件或返回types声明为具有匿名types。 同样,您也不能将方法,属性,构造函数或索引器的forms参数声明为具有匿名types。 要将匿名types或包含匿名types的集合作为parameter passing给方法,可以将参数声明为types对象 。 但是,这样做打破了强打字的目的。

(重点是我的)


更新

你可以使用generics来实现你想要的:

 public void LogEmployees<T>(IEnumerable<T> list) { foreach (T item in list) { } } 

通常情况下,你可以用generics来做这件事,例如:

 MapEntToObj<T>(IQueryable<T> query) {...} 

编译器应该在调用MapEntToObj(query)时推断出T 不太清楚你想在这个方法里面做什么,所以我不能说这是否有用…问题是,在MapEntToObj你仍然不能命名T – 你可以:

  • T调用其他generics方法
  • T上的反思来做事情

但除此之外,操作匿名types是相当困难的 – 至less因为它们是不可变的; -p

另一个技巧( 提取数据时)也是通过一个select器 – 例如:

 Foo<TSource, TValue>(IEnumerable<TSource> source, Func<TSource,string> name) { foreach(TSource item in source) Console.WriteLine(name(item)); } ... Foo(query, x=>x.Title); 

您可以使用generics与以下技巧(铸造为匿名types):

 public void LogEmployees<T>(IEnumerable<T> list) { foreach (T item in list) { var typedItem = Cast(item, new { Name = "", Id = 0 }); // now you can use typedItem.Name, etc. } } static T Cast<T>(object obj, T type) { return (T)obj; } 

“dynamic”也可以用于这个目的。

 var anonymousType = new { Id = 1, Name = "A" }; var anonymousTypes = new[] { new { Id = 1, Name = "A" }, new { Id = 2, Name = "B" }; private void DisplayAnonymousType(dynamic anonymousType) { } private void DisplayAnonymousTypes(IEnumerable<dynamic> anonymousTypes) { foreach (var info in anonymousTypes) { } } 

如果你知道,你的结果实现了一个特定的接口,你可以使用接口作为数据types:

 public void LogEmployees<T>(IEnumerable<T> list) { foreach (T item in list) { } } 

我将使用IEnumerable<object>作为参数的types。 然而,对于不可避免的明确演员来说,这不是一个好的收益。 干杯

而不是传递一个匿名types,传递一个dynamictypes的列表:

  1. var dynamicResult = anonymousQueryResult.ToList<dynamic>();
  2. 方法签名: DoSomething(List<dynamic> _dynamicResult)
  3. 调用方法: DoSomething(dynamicResult);
  4. 完成。

感谢Petar Ivanov !