Sae*_*ati 126 c# parameters function anonymous-types
如何将匿名类型作为参数传递给其他函数?考虑这个例子:
var query = from employee in employees select new { Name = employee.Name, Id = employee.Id };
LogEmployees(query);
Run Code Online (Sandbox Code Playgroud)
query
这里的变量没有强类型.我应该如何定义我的LogEmployees函数来接受它?
public void LogEmployees (? list)
{
foreach (? item in list)
{
}
}
Run Code Online (Sandbox Code Playgroud)
换句话说,我应该使用什么而不是LogEmployees
标记.
Tim*_* S. 163
我认为你应该为这个匿名类型创建一个类.在我看来,这是最明智的做法.但如果你真的不想,你可以使用动态:
public void LogEmployees (IEnumerable<dynamic> list)
{
foreach (dynamic item in list)
{
string name = item.Name;
int id = item.Id;
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,这不是强类型的,因此,例如,如果名称更改为EmployeeName,则在运行时之前您不会知道存在问题.
Jon*_*eet 41
你可以这样做:
public void LogEmployees<T>(List<T> list) // Or IEnumerable<T> list
{
foreach (T item in list)
{
}
}
Run Code Online (Sandbox Code Playgroud)
......但是你不会对每件物品做很多事情.你可以调用toString,但你将无法使用(比方说)Name
和Id
直接.
Jar*_*Par 18
不幸的是,你要做的事情是不可能的.在引擎盖下,查询变量被键入为匿名类型的IEnumerable.匿名类型名称无法在用户代码中表示,因此无法使它们成为函数的输入参数.
最好的办法是创建一个类型并将其用作查询的返回值,然后将其传递给函数.例如,
struct Data {
public string ColumnName;
}
var query = (from name in some.Table
select new Data { ColumnName = name });
MethodOp(query);
...
MethodOp(IEnumerable<Data> enumerable);
Run Code Online (Sandbox Code Playgroud)
但在这种情况下,您只选择一个字段,因此直接选择字段可能更容易.这将导致查询被键入为字段类型的IEnumerable.在这种情况下,列名称.
var query = (from name in some.Table select name); // IEnumerable<string>
Run Code Online (Sandbox Code Playgroud)
Ode*_*ded 10
除非参数类型是,否则不能将匿名类型传递给非泛型函数object
.
public void LogEmployees (object obj)
{
var list = obj as IEnumerable();
if (list == null)
return;
foreach (var item in list)
{
}
}
Run Code Online (Sandbox Code Playgroud)
匿名类型旨在用于方法中的短期使用.
来自MSDN - 匿名类型:
您不能将方法的字段,属性,事件或返回类型声明为具有匿名类型.同样,您不能将方法,属性,构造函数或索引器的形式参数声明为具有匿名类型.要传递匿名类型或包含匿名类型的集合作为方法的参数,可以将参数声明为类型对象.但是,这样做会破坏强类型的目的.
(强调我的)
更新
您可以使用泛型来实现您想要的效果:
public void LogEmployees<T>(IEnumerable<T> list)
{
foreach (T item in list)
{
}
}
Run Code Online (Sandbox Code Playgroud)
通常,您使用泛型执行此操作,例如:
MapEntToObj<T>(IQueryable<T> query) {...}
Run Code Online (Sandbox Code Playgroud)
然后编译器应该推断T
您何时调用MapEntToObj(query)
.不太确定你想在方法中做什么,所以我不知道这是否有用......问题是在MapEntToObj
你内部仍然无法命名T
- 你可以:
T
T
来做事但除此之外,操纵匿名类型非常困难 - 尤其是因为它们是不可变的;-p
另一个技巧(提取数据时)也是传递一个选择器 - 例如:
Foo<TSource, TValue>(IEnumerable<TSource> source,
Func<TSource,string> name) {
foreach(TSource item in source) Console.WriteLine(name(item));
}
...
Foo(query, x=>x.Title);
Run Code Online (Sandbox Code Playgroud)
小智 7
您可以使用泛型与以下技巧(转换为匿名类型):
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;
}
Run Code Online (Sandbox Code Playgroud)
"动态"也可用于此目的.
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)
{
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
116980 次 |
最近记录: |