将匿名类型的列表转换为对象列表
cast list of anonymous type to list of object
我正在尝试创建一个匿名列表,该列表可以容纳任何 data type
且 intellisense
支持但不创建 class
.
所以我在下面找到了使用匿名类型的解决方案。
var list = new[]
{
new { Number = 10, Name = "Smith" },
new { Number = 10, Name = "John" }
}.ToList();
foreach (var item in list)
{
Console.WriteLine(item.Name);
}
但是如果我想要一个 returns 高于匿名类型的方法怎么办。
public List<object> GetData()
{
var list = new[]
{
new { Number = 10, Name = "Smith" },
new { Number = 10, Name = "John" }
}.ToList();
return list;
}
编译时错误:
Cannot implicitly convert type
'System.Collections.Generic.List<>' to 'System.Collections.Generic.List
是否可以将匿名类型的列表转换为具有智能感知支持的对象列表?
更新:
我们不想创建类型的原因,因为我们只想使用匿名类型进行一些数据操作并填充一些其他对象。
以下是可行的方法:
- Return一个
List<object>
,这意味着你在接收端没有intellisense
- Return a
List<dynamic>
,这意味着您在接收端没有智能感知,但也许比通过反射更容易访问您知道的成员
- Return a
List<T>
但是你必须提供一个例子来说明 T
应该是什么样子,这在运行时不会比 dynamic
是
- Return C# 7 附带的新类型的元组
第 1 点和第 2 点可以通过确保列表属于该类型来轻松解决:
...
}.ToList<object>();
第 3 点是一个 hack,但我会 post 下面。
第 4 点可以用以下语法解决:
public List<(int Number, string Name)> GetData()
{
var list = new[]
{
(Number: 10, Name: "Smith"),
(Number: 10, Name: "John")
}.ToList();
return list;
}
这会给你一段时间的智能感知,但属性的命名是编译器的 hack,如果你开始传递这些值,它们很容易退回到 .Item1
和 .Item2
.
要将对象转换为特定类型,您可以使用 hack,它只能在创建匿名对象的同一程序集中工作,也就是说,您的代码中使用了多个匿名类型,它们具有相同的属性,以相同的顺序,具有相同的 属性 类型,最终都是相同的匿名类型。
因此,您可以使用以下骇人听闻的代码将 object
转换为特定的匿名类型:
public T AnonymousCast<T>(object value, T example) => (T)value;
public IEnumerable<T> AnonymousCastAll<T>(IEnumerable<object> collection, T example) => collection.OfType<T>();
您可以像这样在您的案例中使用它:
var d = AnonymousCast(GetData()[0], new { Number = 0, Name = "" });
这并不比使用 dynamic
更安全,因为不能保证从 GetData
实际上 返回的对象是匿名类型。
简而言之,使用命名类型。
我正在尝试创建一个匿名列表,该列表可以容纳任何 data type
且 intellisense
支持但不创建 class
.
所以我在下面找到了使用匿名类型的解决方案。
var list = new[]
{
new { Number = 10, Name = "Smith" },
new { Number = 10, Name = "John" }
}.ToList();
foreach (var item in list)
{
Console.WriteLine(item.Name);
}
但是如果我想要一个 returns 高于匿名类型的方法怎么办。
public List<object> GetData()
{
var list = new[]
{
new { Number = 10, Name = "Smith" },
new { Number = 10, Name = "John" }
}.ToList();
return list;
}
编译时错误:
Cannot implicitly convert type 'System.Collections.Generic.List<>' to 'System.Collections.Generic.List
是否可以将匿名类型的列表转换为具有智能感知支持的对象列表?
更新:
我们不想创建类型的原因,因为我们只想使用匿名类型进行一些数据操作并填充一些其他对象。
以下是可行的方法:
- Return一个
List<object>
,这意味着你在接收端没有intellisense - Return a
List<dynamic>
,这意味着您在接收端没有智能感知,但也许比通过反射更容易访问您知道的成员 - Return a
List<T>
但是你必须提供一个例子来说明T
应该是什么样子,这在运行时不会比dynamic
是 - Return C# 7 附带的新类型的元组
第 1 点和第 2 点可以通过确保列表属于该类型来轻松解决:
...
}.ToList<object>();
第 3 点是一个 hack,但我会 post 下面。
第 4 点可以用以下语法解决:
public List<(int Number, string Name)> GetData()
{
var list = new[]
{
(Number: 10, Name: "Smith"),
(Number: 10, Name: "John")
}.ToList();
return list;
}
这会给你一段时间的智能感知,但属性的命名是编译器的 hack,如果你开始传递这些值,它们很容易退回到 .Item1
和 .Item2
.
要将对象转换为特定类型,您可以使用 hack,它只能在创建匿名对象的同一程序集中工作,也就是说,您的代码中使用了多个匿名类型,它们具有相同的属性,以相同的顺序,具有相同的 属性 类型,最终都是相同的匿名类型。
因此,您可以使用以下骇人听闻的代码将 object
转换为特定的匿名类型:
public T AnonymousCast<T>(object value, T example) => (T)value;
public IEnumerable<T> AnonymousCastAll<T>(IEnumerable<object> collection, T example) => collection.OfType<T>();
您可以像这样在您的案例中使用它:
var d = AnonymousCast(GetData()[0], new { Number = 0, Name = "" });
这并不比使用 dynamic
更安全,因为不能保证从 GetData
实际上 返回的对象是匿名类型。
简而言之,使用命名类型。