C# 如何将匿名类型作为参数传递?
如何将匿名类型作为参数传递给其他函数?考虑这个例子:C# 如何将匿名类型作为参数传递?,c#,function,parameters,anonymous-types,C#,Function,Parameters,Anonymous Types,如何将匿名类型作为参数传递给其他函数?考虑这个例子: var query = from employee in employees select new { Name = employee.Name, Id = employee.Id }; LogEmployees(query); 此处的变量query没有强类型。我应该如何定义我的LogEmployees函数来接受它 public void LogEmployees (? list) { foreach (? item in list
var query = from employee in employees select new { Name = employee.Name, Id = employee.Id };
LogEmployees(query);
此处的变量query
没有强类型。我应该如何定义我的LogEmployees
函数来接受它
public void LogEmployees (? list)
{
foreach (? item in list)
{
}
}
换句话说,我应该用什么来代替
?
标记。不幸的是,你试图做的是不可能的。在后台,查询变量的类型是匿名类型的IEnumerable
。匿名类型名称不能在用户代码中表示,因此无法将其作为函数的输入参数
最好是创建一个类型并将其用作查询的返回,然后将其传递到函数中。比如说,
struct Data {
public string ColumnName;
}
var query = (from name in some.Table
select new Data { ColumnName = name });
MethodOp(query);
...
MethodOp(IEnumerable<Data> enumerable);
通常,您使用泛型执行此操作,例如:
MapEntToObj<T>(IQueryable<T> query) {...}
除非参数类型为
object
,否则不能将匿名类型传递给非泛型函数
public void LogEmployees (object obj)
{
var list = obj as IEnumerable();
if (list == null)
return;
foreach (var item in list)
{
}
}
匿名类型用于方法中的短期使用
从MSDN-:
不能将字段、属性、事件或方法的返回类型声明为具有匿名类型。同样,不能将方法、属性、构造函数或索引器的形式参数声明为具有匿名类型要将匿名类型或包含匿名类型的集合作为参数传递给方法,可以将参数声明为type object。然而,这样做违背了强类型的目的
(强调矿山)
更新 您可以使用泛型实现您想要的:
public void LogEmployees<T>(IEnumerable<T> list)
{
foreach (T item in list)
{
}
}
public void LogEmployees(IEnumerable列表)
{
foreach(列表中的T项)
{
}
}
您可以这样做:
public void LogEmployees<T>(List<T> list) // Or IEnumerable<T> list
{
foreach (T item in list)
{
}
}
public void LogEmployees(List)//或IEnumerable List
{
foreach(列表中的T项)
{
}
}
。。。但你不会对每一项都做太多。您可以调用ToString,但不能直接使用(比如)
Name
和Id
。如果您知道,您的结果实现了某个接口,您可以将该接口用作数据类型:
public void LogEmployees<T>(IEnumerable<T> list)
{
foreach (T item in list)
{
}
}
public void LogEmployees(IEnumerable列表)
{
foreach(列表中的T项)
{
}
}
我将使用IEnumerable
作为参数的类型。然而,对于不可避免的显性演员来说,这并不是一个很大的收获。
干杯我想你应该为这种匿名类型的人上课。在我看来,那是最明智的做法。但如果您真的不想,可以使用动力学:
public void LogEmployees (IEnumerable<dynamic> list)
{
foreach (dynamic item in list)
{
string name = item.Name;
int id = item.Id;
}
}
public void LogEmployees(IEnumerable列表)
{
foreach(列表中的动态项)
{
字符串名称=item.name;
int id=item.id;
}
}
请注意,这不是强类型,因此,例如,如果名称更改为EmployeeName,则在运行时之前您不会知道有问题。您可以使用具有以下技巧的泛型(强制转换为匿名类型):
public void LogEmployees(IEnumerable列表)
{
foreach(列表中的T项)
{
var typedItem=Cast(项,新的{Name=”“,Id=0});
//现在可以使用typedItem.Name等。
}
}
静态T型转换(对象对象对象,T型)
{
返回(T)obj;
}
“动态”也可用于此目的
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)
{
}
}
var anonymousType=new{Id=1,Name=“A”};
var anonymousTypes=new[]{new{Id=1,Name=“A”},new{Id=2,Name=“B”};
私有void DisplayAnonymousType(动态anonymousType)
{
}
私有void DisplayAnonymousTypes(IEnumerable anonymousTypes)
{
foreach(匿名类型中的var信息)
{
}
}
不要传递匿名类型,而是传递动态类型的列表:
var dynamicResult=anonymousQueryResult.ToList();
DoSomething(List\u dynamicResult)
DoSomething(dynamicResult);
多亏了!我的例子是一个,但大多数情况下更多。你的答案是有效的(现在也很明显)。我只需要休息一下思考一下;-)仅供参考:从一个警告中可以看出,当你创建一个合适的类
Equals
时,会改变行为。也就是说,你必须实现它。(我知道这一差异,但在重构过程中仍然设法忘记了它。)如果无法传递匿名类型(或匿名类型的集合)对于方法,整个LINQ都会失败。可以,只是方法必须是完全通用的,而不是使用匿名类型的属性。reobject
-或dynamic
;带“as”的pIf casting应该检查列表是否为null“can”!=“have to”根据我的回答,使用object
与在匿名类型中使用泛型方法不同。除了可以在第一行末尾使用其中T:some type
来缩小类型。不过,在这一点上,期望某种类型的公共接口比期望接口更有意义。:)@d_r_w:您不能将where t:some type
用于匿名类型,因为它们没有实现任何类型的接口…@dlev:您不能这样做,foreach要求变量在实现GetEnumerator上迭代,而匿名类型不能保证这一点。@Jon Skeet:好的,我的大脑今天早上动力不足。@Jonsket.我支持如果T是匿名类型,您可以使用反射仍然访问/设置属性,对吗?我正在考虑这样一种情况:有人编写“Select*from”语句并使用匿名(或已定义)语句类来定义查询结果中哪些列映射到匿名对象上相同的命名属性。由于动态用法,我将此作为正确答案进行了检查。我真的很方便。谢谢:)我同意,一旦开始传递数据,通常可能/应该首选更结构化的方式,以避免引入uce很难找到bug(你避开了类型系统)。但是,如果你想找到一个折衷方案,另一种方法就是简单地传递一个generi
public void LogEmployees (IEnumerable<dynamic> list)
{
foreach (dynamic item in list)
{
string name = item.Name;
int id = item.Id;
}
}
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;
}
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)
{
}
}