返回匿名类型

3

我正在使用一种技巧来返回匿名类型,但是我不确定它是否适用于所有情况。如果使用此技巧存在任何问题,请告诉我,以便我不会在我的项目中使用这段代码。

class A
{
    public int ID { get; set; }
    public string Name { get; set; }
}

class B
{
    public int AID { get; set; }
    public string Address { get; set; }
}

private List<object> GetJoin()
{
    var query = from a in objA
                join b in objB
                on a.ID equals b.AID
                select new { a.ID, a.Name, b.Address };
    List<object> lst = new List<object>();
    foreach (var item in query)
    {
        object obj = new { ID = item.ID, Name = item.Name, Address = item.Address };
        lst.Add(obj);
    }
    return lst;
}
T Cast<T>(object obj, T type)
{
    return (T)obj;
}

//call Anonymous Type function
foreach (var o in GetJoin())
{
    var typed = Cast(o, new { ID = 0, Name = "", Address = "" });
    int i = 0;
}

2
大问题是:为什么不创建一个名义类型,完全放弃这些花招呢?class NameAndAddress { public int ID { get; set; } public string Name { get; set; } public string Address { get; set; } }。问题解决了。 - R. Martinho Fernandes
因为我不想为每个LINQ查询创建一个类。 - Ulhas Tuscano
你想为了少写几个属性而放弃类型安全和可读性吗?这肯定不比每次使用时都强制创建一个虚拟匿名对象更费力。按示例转换适用于对象类型仅对调用者有影响的情况。但当它对被调用者有影响时,这种方法就很糟糕了。 - R. Martinho Fernandes
2个回答

11

如果所有内容都在同一个程序集中,那么这是肯定可行的。但是,如果跨越程序集边界,它将不起作用-匿名类型是内部的,“标识”基于:

  • 正在使用的程序集
  • 属性:
    • 名称
    • 类型
    • 顺序

一切都需要恰到好处,才能被认为是相同的类型。

不过,这种方法并不是很好。例如,您的GetJoin方法可以简化为:

return (from a in objA
        join b in objB
        on a.ID equals b.AID
        select (object) new { a.ID, a.Name, b.Address })
       .ToList();

另外,你失去了编译时的类型安全和可读性。我认为,创建一个真正的类型来封装这些数据会更好。不可否认,如果我们能够创建一个命名类型,它与匿名类型等效,只是带有一个名称,那将会很不错...但目前还没有这个功能 :(


0

如果不使用 Object 类型,无法返回匿名类型。而使用 Object 类型,则会失去成员访问权限。

您有两个选择:

  • 创建一个类型。(推荐)
  • 使用 dynamic 类型来访问成员。

1
这就是 OP 的 Cast 方法的全部意义。它使用示例转换来将 object 重新转换为正确的匿名类型。话虽如此,在任何非一次性代码中这样做都是一个非常糟糕的想法。 - LukeH

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接