将匿名类型的列表强制转换为对象列表

问题描述 投票:-3回答:1

我正在尝试创建一个匿名列表,可以保持任何data typeintellisense支持但没有创建class

所以我发现下面的解决方案使用匿名类型。

  var list = new[]
  { 
     new { Number = 10, Name = "Smith" },
     new { Number = 10, Name = "John" } 
  }.ToList();

  foreach (var item in list)
  {
    Console.WriteLine(item.Name);
  }

但是如果我想要一个返回匿名类型的方法呢?

public List<object> GetData()
{

    var list = new[]
    {
        new { Number = 10, Name = "Smith" },
        new { Number = 10, Name = "John" }
    }.ToList();

    return list;

}

编译时错误:

无法将类型'System.Collections.Generic.List <>'隐式转换为'System.Collections.Generic.List

是否可以将匿名类型列表转换为具有intellisense支持的对象列表?

更新:

我们不想创建类型的原因,因为我们只想使用匿名类型进行一些数据操作并填充其他所有对象。

c# anonymous-types
1个回答
2
投票

以下是可能的方法:

  1. 返回一个List<object>,这意味着你在接收端没有智能感知
  2. 返回一个List<dynamic>,这意味着你在接收端没有智能感知,但也许比通过反射更容易访问你认识的成员
  3. 返回一个List<T>然后你将不得不提供一个如何看T的例子,这在运行时不会比dynamic更安全
  4. 返回C#7附带的新类型的元组

只需确保列表属于该类型,即可轻松解决第1点和第2点:

...
}.ToList<object>();

第3点是黑客,但我会在下面发布。

可以使用以下语法解决第4点:

public List<(int Number, string Name)> GetData()
{

    var list = new[]
    {
        (Number: 10, Name: "Smith"),
        (Number: 10, Name: "John")
    }.ToList();

    return list;
}

这将给你智能感知一段时间,但属性的命名是编译器的黑客攻击,如果你开始传递这些值,他们将很容易回落到.Item1.Item2


要将对象转换为特定类型,您可以使用hack,该hack仅在创建匿名对象的同一程序集中工作,这就是代码中使用的多个匿名类型,它们具有相同的属性,在同一个订单,具有相同的属性类型,最终都是相同的匿名类型。

因此,你可以使用这个hackish代码将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返回的对象实际上是匿名类型。

简而言之,使用命名类型。

© www.soinside.com 2019 - 2024. All rights reserved.