【问题标题】:How to return a generic list collection in C#?如何在 C# 中返回通用列表集合?
【发布时间】:2010-12-28 13:57:23
【问题描述】:

我有一些 linq to sql 方法,当它执行查询时,它会返回一些匿名类型。

我想将该匿名类型返回到我的服务层,以便对其进行一些逻辑和处理。

我不知道怎么退货。

我以为我能做到这一点

public List<T> thisIsAtest()
{
     return query;
}

但我收到此错误

Error   1   The type or namespace name 'T' could not be found (are you missing a using directive or an assembly reference?)

所以不确定我缺少哪个程序集,或者是否是这种情况。

谢谢

编辑

好的,我的第一个问题已经解决,但现在我有一个新问题,我不知道如何解决,因为我对匿名类型了解不多。

我收到此错误

不能隐式转换类型 'System.Collections.Generic.List' 到'System.Collections.Generic.List

这里是查询

   DbContext.Table.Where(u => u.Table.UserId == userId && u.OutOFF != 0)
       .GroupBy(u => new { u.Table.Prefix })
       .Select(group => new { prefix = group.Key, 
                              Marks = group.Sum(item => (item.Mark * item.Weight) / item.OutOFF) })
       .ToList();

编辑 2

public class ReturnValue
{
   string prefix { get; set; }
   decimal? Marks { get; set; } 
}

public List<ReturnValue> MyTest(Guid userId)
{
   try
   {
       var result = dbContext.Table.Where(u => u.Table.UserId == userId && u.OutOFF != 0).GroupBy(u => new { u.Table.Prefix })
       .Select(group => new { prefix = group.Key, Marks = group.Sum(item => (item.Mark * item.Weight) / item.OutOFF) }).ToList();
       return result;
   }
   catch (SqlException)
   {
       throw;
   }

选择里面有这个

Anonymous Types:

a is new{string Prefix}
b is new{ 'a prefix, decimal? marks}

【问题讨论】:

  • 为什么不能只定义一个新类型class ReturnValue { int prefix; decimal Marks; } 然后返回一个new ReturnValue(....) 而不是匿名类型??
  • 我需要一个例子。我在进行此查询时得到了帮助,它可以满足我的要求,但如果可以更改或添加一些内容以使其不是匿名的,我完全赞成。
  • 你没有使用我提到的代码!在.Select() 中,您需要使用:.Select(group =&gt; new RETURNVALUE { prefix = group.Key, ... - 这不是您所拥有的!您没有添加在 .Select() 中创建的 TYPE - 那是您的问题

标签: c# .net generics anonymous-types anonymous-methods


【解决方案1】:

如果将泛型列表声明为全局变量,则无需使用 return。无论如何,我在我的代码中使用了 return 函数只是因为 marc_s 说我不能。哈哈

 public static class Globals
    {
        public static List<string> CurPart = new List<string>();
    }
    public List<string> MSQueryRead1DArray(string sql, string db)
    {
        return Globals.CurPart;
    }

【讨论】:

    【解决方案2】:

    你不能 - 句号。您不能在其自身范围之外使用匿名类型,例如您不能将它们作为方法的返回值返回。

    如果你需要返回它们,你需要定义一个新的具体类而不是匿名类型,并使用它来代替匿名类型。

    请参阅 Rick Strahl 的 blog post 关于匿名类型的范围,并参阅 MSDN docs here 明确说明:

    匿名类型具有方法范围。到 传递一个匿名类型,或者一个 包含匿名的集合 类型,在方法边界之外,你 必须首先将类型转换为对象。 然而,这打败了强者 匿名类型的类型。如果你 必须存储您的查询结果或通过 它们在方法边界之外, 考虑使用一个普通的命名 结构或类而不是 匿名类型。

    好的,当然 - 确实有一些肮脏可怕的黑客可以返回匿名类型。但是,如果 Microsoft 的 MSDN AND Jon Skeet 不鼓励这种做法,那么 - 不要这样做。根据定义和意图,匿名类型绑定到定义它们的方法。

    UPDATE for chobo2:我不知道你的数据类型是什么——只是猜测——但假设“prefix”是一个 int 而“marks”是一个小数,你可以定义一个新类:

    public class ReturnValue
    {
        int prefix { get; set; }
        decimal Marks { get; set; } 
    }  
    

    然后你的代码将是一个返回List&lt;ReturnValue&gt;的方法:

    public List<ReturnValue> thisIsAtest()
    {
       DbContext.Table.Where(u => u.Table.UserId == userId && u.OutOFF != 0)
         .GroupBy(u => new { u.Table.Prefix })
         .Select(group => new ReturnValue 
                              { prefix = group.Key, 
                                Marks = group
                                  .Sum(item => (item.Mark * item.Weight) / item.OutOFF) })
         .ToList();
    }
    

    这里的关键是:在你的.Select 方法中,而不是创建一个匿名类型的新实例:

         .Select(group => new { prefix = group.Key, marks = .... }
    

    你创建一个具体类型的实例:

         .Select(group => new ReturnValue { prefix = group.Key, marks = .... }
    

    这样,您将拥有一个具体的类 ReturnValue - 可以随意命名 - 然后您可以轻松地返回该类型的列表,并在其他地方使用该类型。

    【讨论】:

    • 其实你可以:msmvps.com/blogs/jon_skeet/archive/2009/01/09/… 不过我不推荐。
    • 嗯,我可以看一个例子。我现在明白了。我不想在我的存储库层中执行逻辑,否则我必须制作 2 个相同的方法,因为我使用它来放置但需要以 2 种不同的方式使用数据。无法将类型 'System.Collections.Generic.List' 隐式转换为 'System.Collections.Generic.List
    • @MarkByers:但乔恩本人说:“不要使用此代码”......真的,出于所有意图和目的:不要 -甚至不要尝试。
    • 这不是真的。您可以将匿名类型的实例返回为objects。我并不是说这是好的做法,但这是可能的。也就是说,public object DoNotDoThis() { return new { FirstName = "Donald", LastName = "Knuth" }; } 是合法的。
    • @Jason: 是的,理论上 - 但这会破坏所有类型安全和一切。不要这样做 - 如果您需要返回它,只需创建一个真正的具体类 - 更容易和更清洁。
    【解决方案3】:

    匿名类型非常有限,您只能在声明它们的方法范围内使用它们。

    您可以将它们作为普通对象传回,但是您会丢失类型信息。我见过一些传递匿名类型的解决方案;但他们稍后会使用反射来检索属性。

    【讨论】:

      【解决方案4】:

      您想从常规方法返回匿名类型吗?我很确定你可以使用反射,但不会有类型安全和一大堆其他问题。更不用说从调用代码的角度来看它看起来很奇怪。我认为你基本上必须返回对象。

      你最好使用一个类或结构并将值填充在那里。

      【讨论】:

        【解决方案5】:
        public List<T> thisIsAtest<T>()
        {
             return query;
        }
        

        【讨论】:

        • 解决了这个问题,但现在我得到了无法将类型'System.Collections.Generic.List'隐式转换为'System.Collections.Generic.List
        • 你返回的查询是一个匿名类型的列表,你只能返回一个的列表。您可以使用 Jon Skeet 的 objects 和 cast hack,但强烈不推荐。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-04-03
        • 2013-04-13
        • 2020-11-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-19
        相关资源
        最近更新 更多