【问题标题】:Accessing C# Anonymous Type Objects访问 C# 匿名类型对象
【发布时间】:2009-04-03 11:13:23
【问题描述】:

如何在声明的范围之外访问匿名类型的对象?

例如

void FuncB()
{
var obj = FuncA();
Console.WriteLine(obj.Name);
}

??? FuncA()
{
var a = (from e in DB.Entities
where e.Id == 1
select new {Id = e.Id, Name = e.Name}).FirstOrDefault();

return a;
}

【问题讨论】:

标签: c# anonymous-types


【解决方案1】:

正如其他答案所述,你真的不应该这样做。但是,如果你坚持,那么有一个令人讨厌的黑客被称为“以身作则”,它可以让你做到这一点。该技术在几篇文章中提到,herehere

public void FuncB()
{
    var example = new { Id = 0, Name = string.Empty };

    var obj = CastByExample(FuncA(), example);
    Console.WriteLine(obj.Name);
}

private object FuncA()
{
    var a = from e in DB.Entities
            where e.Id == 1
            select new { Id = e.Id, Name = e.Name };

    return a.FirstOrDefault();
}

private T CastByExample<T>(object target, T example)
{
    return (T)target;
}

(虽然the author of one of those articles says that he doesn't want to be associated with it either,但我不能把功劳归于这个黑客。他的名字可能很熟悉。)

【讨论】:

  • 被打败了8秒!我已经删除了我的(复制它没有好处)。但要强调:: 不要这样做 ;-p
  • 所以您已接受此作为您的首选答案。虽然这是一种有趣的技术,但我强烈建议不要在任何重要/生产代码中使用它!
  • 是的。很高兴知道这是可以做到的。虽然真的很邪恶,但我也是。muhahhhhahahaaaa。
  • 谢谢,我没有使用它 :)) 我最终只使用了不可变结构。
  • 这个 hack 确实有一个特定的警告,它不能跨越程序集边界。这是因为编译器会根据每个程序集的签名生成一次类型,因此如果您在与 FuncA() 不同的程序集中使用 var example = new { Id = 0, Name = string.Empty };,则类型将不匹配。
【解决方案2】:

您不能从函数返回匿名类型。

来自MSDN documentation

要在方法边界之外传递匿名类型或包含匿名类型的集合,您必须首先将类型强制转换为对象。然而,这破坏了匿名类型的强类型。如果您必须存储查询结果或将它们传递到方法边界之外,请考虑使用普通的命名结构或类而不是匿名类型。

【讨论】:

    【解决方案3】:

    如果您使用的是 .NET 4.0,则可以为此使用元组,您将返回 Tuple&lt;int, string&gt;。您可以为 2.0/3.5 实现自己的元组,实际上其他人已经拥有,所以如果您愿意,您应该可以这样做。

    【讨论】:

      【解决方案4】:

      匿名类型只是编译器生成的类,编译器不愿意告诉你类本身的名称。因此,除了返回对 object 的引用之外,您无法从函数返回此类的实例。

      【讨论】:

        【解决方案5】:

        嗯,我认为答案是:不要在声明的范围之外使用匿名类型。在这种情况下,创建一个简单类型。

        【讨论】:

          【解决方案6】:

          开源框架Impromptu-Interface 将允许您将匿名对象强制转换为接口。它的优点是不那么 hacky,因为它可以跨程序集边界按预期工作。它使用轻量级代理和 dlr 来实现这一点。

          【讨论】:

            【解决方案7】:

            将为这种情况创建一个类:

            public class LISTFUNCA   
            {                         
                public int identificacion;  
                public string nombre;      
            }     
            

            然后:

            public List<LISTFUNCA> FuncA()   
            {                                          
                var lista = (from e in DB.Entities where e.Id == 1                        
                            select new { identificacion = e.Id, nombre = e.Name})
                            .FirstOrDefault();  
                return lista.ToList(); 
            }     
            

            【讨论】:

            • 请检查您的代码;我重新格式化了它,但我认为它不正确。另外,请阅读faq 了解有关如何正确格式化代码的详细信息。而且,当您发布的内容看起来很糟糕时,请不要忘记您可以edit your post to fix it.
            猜你喜欢
            • 2016-12-31
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-12-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多