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

时间:2017-12-19 13:01:21

标签: c# anonymous-types

我正在尝试创建一个匿名列表,该列表可以保留任何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);
  }

但是,如果我想要一个返回匿名类型的方法,该怎么办?

public List<object> GetData()
{

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

    return list;

}

编译时间错误:

  

无法隐式转换类型   'System.Collections.Generic.List&LT;&GT;'到'System.Collections.Generic.List

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

更新

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

1 个答案:

答案 0 :(得分:2)

以下是可能的方法:

  1. 返回List<object>,表示您在接收端没有智能感知
  2. 返回List<dynamic>,这意味着您在接收端没有智能感知,但可能比通过反射更容易访问您认识的成员
  3. 返回一个List<T>,但是你必须提供T应该看起来如何的例子,这在运行时不会比dynamic更安全
  4. 返回C#7附带的新类型的元组
  5. 只需确保列表属于该类型,即可轻松解决第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。 / p>

    要将对象强制转换为特定类型,您可以使用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 实际返回的对象属于匿名类型。

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