【问题标题】:Anonymous type for datarow-object isn't working数据行对象的匿名类型不起作用
【发布时间】:2023-04-11 05:19:01
【问题描述】:

我想从数据行中选择一些字段,例如:

var result = datatable.AsEnumerable()
    .Select(x => new { x.Field<string>("Field1"), x.Field<string>("Field2")});

不幸的是,这行不通:

匿名类型成员声明器无效。必须使用成员分配、简单名称或成员访问来声明匿名类型成员。

我怎样才能实现我想要的?

编辑:似乎(至少)有两种方法可以实现它:

  1. 为他们命名:

    var 结果 = datatable.AsEnumerable().Select(x => new { Field1 = x.Field("Field1"), Field2 = x.Field("Field2") });
  2. 创建一个新对象

假设我们有一个类

class MyClass
{
    public string Field1 { get; set; }
    public string Field2 { get; set; }

    public MyClass(string field1, string field2)
    {
        this.Field1 = field1;
        this.Field2 = field2;
    }
}

我们可以做到以下几点:

var result = datatable.AsEnumerable()
    .Select(x => new MyClass(x.Field<string>("Field1"), x.Field<string>("Field2")));

【问题讨论】:

  • 有一个使用元组的答案,我更喜欢它,因为我需要将结果集转换为我自己的类。不幸的是,有人删除了答案...
  • 为什么需要Tuple 来创建自己的类?
  • 我在我的回答中添加了一个元组示例,但是,如果你愿意,你应该在问题中明确说明。
  • .Net 3.5 中没有元组
  • 我认为这可能是另一个问题,所以我没有添加它。 @Mario:我不需要一个元组来创建我的类,我只是将它替换为我的类,采用三个参数......

标签: c# linq .net-3.5 anonymous-types datarow


【解决方案1】:

你需要给你的匿名类型的成员一些名字。

var result = datatable.AsEnumerable()
    .Select(x => new { 
        Field1 = x.Field<string>("Field1"), 
        Field2 = x.Field<string>("Field2")});

如果您考虑一下,没有名称会使以后引用属性变得非常困难,您必须使用反射和一些猜测工作。在任何情况下,都需要定义名称,以便可以在幕后为您创建匿名类型。


如果您更喜欢返回 Tuple 而不是匿名类型,您可以这样做

    var result = datatable.AsEnumerable()
    .Select(x => Tuple.Create( 
        Field1 = x.Field<string>("Field1"), 
        Field2 = x.Field<string>("Field2")));

然后你就可以分别访问Item1Item2的成员了。

但是Tuple 类是 .Net 4.0 的新成员,您的问题被标记为 3.5


响应您的评论,您可以随时声明自己的类型

public class MyPair<TItem1, TItem2>
{
    public MyPair(TItem1 item1, TItem2 item2)
    {
        this.Item1 = item1;
        this.Item2 = item2;
    }

    public TItem1 Item1 { get; private set; }
    public TItem2 Item2 { get; private set; }
}

显然你会这样使用,

var result = datatable.AsEnumerable()
    .Select(x => new MyPair( 
        Field1 = x.Field<string>("Field1"), 
        Field2 = x.Field<string>("Field2")));

【讨论】:

  • “你必须使用反射” 以及你用来定位属性的名称是什么...... :)
  • @gdoron,是的,这些名字很重要。
  • 无元组,但替换工作方式相同,不需要命名任何匿名类型,例如... .Select(x => new MyObject(x.Field("Field_1") , x.Field("Field_2"))
【解决方案2】:

您需要为属性命名:

var result = datatable.AsEnumerable()
    .Select(x => new 
    { 
        Field1 = x.Field<string>("Field1"), 
        Field2 = x.Field<string>("Field2")
    });

然后使用它:

var field1 = result.First().Field1;

编译器不知道如何从x.Field&lt;string&gt;("Field1") 之类的东西中推断出名称。但这会起作用:

int id = 1;
string name = "Myname";
var obj = new { id, name }; // Names are inferred from the variable name.

var result = obj.name; // This would work

【讨论】:

    【解决方案3】:

    好吧,错误说明了一切,给成员起名字:

    var result = datatable.AsEnumerable()
    .Select(x => new { 
                        First = x.Field<string>("Field1"),
                        Second = x.Field<string>("Field2")
                     });
    

    【讨论】:

      猜你喜欢
      • 2020-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-05
      相关资源
      最近更新 更多