返回类型是List的意思是什么?

10

嗨,我需要找到一种方法来为方法声明一个匿名类型。这是我的代码:

public List<var> ListOfProducts(string subcategory)
{
    var products = (from p in dataContext.Products
                    join s in dataContext.SubCategories.Where(x => x.SubCatName == subcategory)
                        on p.SubcatId equals s.SubCatId
                    join b in dataContext.Brands on p.BrandId equals b.BrandId
                    select new
                    {
                        Subcategory = s.SubCatName,
                        Brand = b.BrandName,
                        p.ProductName,
                        p.ProductPrice
                    });
    return products;
} 

我不知道在这个方法中应该设置什么类型的列表。在这种情况下我该怎么做?


2
我认为你不能这样做,因为该类型是局部于该方法的。声明一个公共类型,让其他人可以实际使用它。 - poke
2
你会如何使用这个方法? - SWeko
2
我在你的另一个问题中已经给出了答案——你需要声明自己的类及其属性。你不理解我的早期评论中哪一部分呢? - Jon Skeet
根据您使用该方法的方式,您可能需要类似于此的东西https://dev59.com/UXRB5IYBdhLWcg3weHLx - pymendoza
可能是返回匿名类型?的重复问题。 - nawfal
4个回答

21

你不能从一个方法中返回一个匿名类型

只需为您的类型创建一个类并返回即可。

public class Product
{
    string Subcategory { get; set; }
    string Brand { get; set; }
    string ProductName { get; set; }
    decimal ProductPrice { get; set; }
}

然后按照这样返回:

var products = (from p in dataContext.Products
                    join s in dataContext.SubCategories.Where(x => x.SubCatName == subcategory) on p.SubcatId
                        equals s.SubCatId
                    join b in dataContext.Brands on p.BrandId equals b.BrandId
                    select new Product
                               {
                                   Subcategory = s.SubCatName,
                                   Brand = b.BrandName,
                                   p.ProductName,
                                   p.ProductPrice
                               });

    return products;

编辑:为了澄清我的第一句话,正如@JamesMichaelHare所指出的那样,从方法中返回匿名类型是可能的,通过返回objectdynamic,但这可能会比它值得的麻烦更多,因为你必须使用Reflection或其他访问对象属性的方式。


这是我会做的方式。 - Gromer
1
只是澄清一下,您是正确的,不能将方法的返回类型设置为匿名类型,但是可以从方法中返回匿名对象(作为object、dynamic等),尽管如果对象在生命周期中超出方法的范围,则匿名类型并不是最好的选择,最好使用自定义类。您说得很对,只是想确保他们不会误解为无法返回匿名对象本身... - James Michael Hare

9
根据MSDN的说明,dynamic类型使其所用操作可以绕过编译时类型检查。相反,这些操作将在运行时解决。因此,请尝试使用以下内容:
public IEnumerable<dynamic> ListOfProducts(string subcategory) 

4

我的建议是,你应该为此定义另一个模型。如果你将返回的结果用于表示层,则应该定义ViewModel;如果你用于分发层,则可以将其定义为Dto对象。

public class ProductDto
{
    public string Subcategory {get; set; }
    public string Brand { get; set; }
    public string ProductName{ get; set; }
    public decimal ProductPrice{ get; set; }
}

2

请注意:匿名类型设计用于方法(或函数)范围内使用,而不是在外部使用。

但是可以通过一些扩展方法和一些额外的转换来实现(我不喜欢这样做):

(在您的代码中,您还应该将.ToList()添加到LINQ表达式中。)

扩展方法如下:

static List<T> InitList<T>(this T o) { return new List<T>(); }
static T CastToThis<T>(this  T target, object o) { return (T)o; }

你可以通过以下方式初始化匿名类型的列表:

var list = new { Name = "Name", Age = 40 }.InitList();

现在,通过以下方式将方法返回的对象转换为此列表的类型:
list = list.CastToThis(returnedValueOfYourMethod);

另外一件事:匿名类型仅在程序集内部有效,无法跨越程序集边界传递。引自这里

C#规范保证,当您在一个程序集中的两个地方使用“相同”的匿名类型时,这些类型将统一成一个类型。为了“相同”,这两个匿名类型必须拥有完全相同的成员名称和成员类型,并且以完全相同的顺序出现。

总之,我不明白为什么需要这样做,因为声明新类型更加实用,如果真的需要这个功能,您应该研究一下C#中的动态类型,如果您想要进行更多的神奇操作,可以使用反射。


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