在C#中返回匿名类型

fre*_*hie 90 .net c# anonymous-types return-type

我有一个返回匿名类型的查询,查询在方法中.你怎么写的:

public "TheAnonymousType" TheMethod(SomeParameter)
{
  using (MyDC TheDC = new MyDC())
  {
     var TheQueryFromDB = (....
                           select new { SomeVariable = ....,
                                        AnotherVariable = ....}
                           ).ToList();

      return "TheAnonymousType";
    }
}
Run Code Online (Sandbox Code Playgroud)

aba*_*hev 85

你不能.

你只能返回object,或物体的容器,例如IEnumerable<object>,IList<object>等等.

  • 或者`动态`.这使得它更容易使用. (49认同)
  • 使用*dynamic*不是解决方案,匿名类型的字段不是公共的,它们是内部的. (10认同)
  • @HansPassant假设调用者在同一个程序集中,那么它仍然(有些)有用.对于它的价值,这些字段是公开的 - 类型是内部的.我一般都在营地,你不应该回归匿名类型. (7认同)
  • @frenchie:是的,只在会员的内部.如果你想归还它 - 把它变成一个众所周知的类型. (2认同)

Not*_*ple 40

您可以返回dynamic,它将为您提供匿名类型的运行时检查版本,但仅限于.NET 4+


Jus*_*ony 25

您无法返回匿名类型.你能创建一个可以返回的模型吗?否则,你必须使用object.

这是Jon Skeet关于这个主题的文章

文章代码:

using System;

static class GrottyHacks
{
    internal static T Cast<T>(object target, T example)
    {
        return (T) target;
    }
}

class CheesecakeFactory
{
    static object CreateCheesecake()
    {
        return new { Fruit="Strawberry", Topping="Chocolate" };
    }

    static void Main()
    {
        object weaklyTyped = CreateCheesecake();
        var stronglyTyped = GrottyHacks.Cast(weaklyTyped,
            new { Fruit="", Topping="" });

        Console.WriteLine("Cheesecake: {0} ({1})",
            stronglyTyped.Fruit, stronglyTyped.Topping);            
    }
}
Run Code Online (Sandbox Code Playgroud)

或者,这是另一篇类似的文章

或者,正如其他人正在评论,你可以使用 dynamic

  • 当然我可以创建一个类型; 我本来是想避免这样做. (7认同)

Ros*_*sim 19

在C#7中,我们可以使用元组来完成这个:

public List<(int SomeVariable, string AnotherVariable)> TheMethod(SomeParameter)
{
  using (MyDC TheDC = new MyDC())
  {
     var TheQueryFromDB = (....
                       select new { SomeVariable = ....,
                                    AnotherVariable = ....}
                       ).ToList();

      return TheQueryFromDB
                .Select(s => (
                     SomeVariable = s.SomeVariable, 
                     AnotherVariable = s.AnotherVariable))
                 .ToList();
  }
}
Run Code Online (Sandbox Code Playgroud)

您可能需要安装System.ValueTuplenuget包.

  • 值得注意的是,如果您决定对命名元组进行 JSON 序列化,它将为您提供 `{Item1: xxx, Item2: xxx}` 等(如 - 名称丢失) (6认同)

cra*_*s84 17

在需要返回时,您可以使用Tuple类替代匿名类型:

注意:元组最多可以有8个参数.

return Tuple.Create(variable1, variable2);
Run Code Online (Sandbox Code Playgroud)

或者,对于原始帖子的示例:

public List<Tuple<SomeType, AnotherType>> TheMethod(SomeParameter)
{
  using (MyDC TheDC = new MyDC())
  {
     var TheQueryFromDB = (....
                           select Tuple.Create(..., ...)
                           ).ToList();

      return TheQueryFromDB.ToList();
    }
}
Run Code Online (Sandbox Code Playgroud)

http://msdn.microsoft.com/en-us/library/system.tuple(v=vs.110).aspx


San*_*eep 10

C#编译器是一个两阶段编译器.在第一阶段,它只检查名称空间,类层次结构,方法签名等.方法主体仅在第二阶段编译.

在编译方法体之前,不确定匿名类型.

因此编译器无法在第一阶段确定方法的返回类型.

这就是为什么匿名类型不能用作返回类型的原因.

正如其他人所建议的那样,如果你使用.net 4.0或grater,你可以使用Dynamic.

如果我是你,我可能会创建一个类型并从该方法返回该类型.这样,对于维护代码且更具可读性的未来程序员来说,这很容易.


Ivo*_*Ivo 8

三种选择:

选项1:

public class TheRepresentativeType {
    public ... SomeVariable {get;set;}
    public ... AnotherVariable {get;set;}
}

public IEnumerable<TheRepresentativeType> TheMethod(SomeParameter)
{
   using (MyDC TheDC = new MyDC())
   {
     var TheQueryFromDB = (....
                           select new TheRepresentativeType{ SomeVariable = ....,
                                        AnotherVariable = ....}
                           ).ToList();

     return TheQueryFromDB;
   } 
}
Run Code Online (Sandbox Code Playgroud)

选项2:

public IEnumerable TheMethod(SomeParameter)
{
   using (MyDC TheDC = new MyDC())
   {
     var TheQueryFromDB = (....
                           select new TheRepresentativeType{ SomeVariable = ....,
                                        AnotherVariable = ....}
                           ).ToList();
     return TheQueryFromDB;
   } 
}
Run Code Online (Sandbox Code Playgroud)

你可以把它作为对象迭代

选项3:

public IEnumerable<dynamic> TheMethod(SomeParameter)
{
   using (MyDC TheDC = new MyDC())
   {
     var TheQueryFromDB = (....
                           select new TheRepresentativeType{ SomeVariable = ....,
                                        AnotherVariable = ....}
                           ).ToList();

     return TheQueryFromDB; //You may need to call .Cast<dynamic>(), but I'm not sure
   } 
}
Run Code Online (Sandbox Code Playgroud)

并且您将能够将其作为动态对象进行迭代并直接访问其属性


Alb*_*rtK 5

使用C# 7.0我们仍然无法返回匿名类型,但我们支持元组类型,因此我们可以返回tuple(System.ValueTuple<T1,T2>在这种情况下)的集合。目前Tuple types 在表达式树中不受支持,您需要将数据加载到内存中。

您想要的代码的最短版本可能如下所示:

public IEnumerable<(int SomeVariable, object AnotherVariable)> TheMethod()
{
    ...

    return (from data in TheDC.Data
        select new { data.SomeInt, data.SomeObject }).ToList()
        .Select(data => (SomeVariable: data.SomeInt, AnotherVariable: data.SomeObject))
}
Run Code Online (Sandbox Code Playgroud)

或者使用流畅的 Linq 语法:

return TheDC.Data
    .Select(data => new {SomeVariable: data.SomeInt, AnotherVariable: data.SomeObject})
    .ToList();
    .Select(data => (SomeVariable: data.SomeInt, AnotherVariable: data.SomeObject))
Run Code Online (Sandbox Code Playgroud)

使用C# 7.1我们可以省略元组的属性名称,它们将从元组初始化中推断出来,就像它适用于匿名类型一样:

select (data.SomeInt, data.SomeObject)
// or
Select(data => (data.SomeInt, data.SomeObject))
Run Code Online (Sandbox Code Playgroud)