在c#中使用LINQ . select时如何维护类型?

本文关键字:何维护 维护 类型 select LINQ | 更新日期: 2023-09-27 18:03:06

我试图返回一组不同的结果,首先使用Substring修剪,但是当我调用"Select"时,它将其转换为匿名类型。我似乎无法得到这个来维护类型"列表"。我只需要返回Select方法中指定的字段。

public List<Facility> GetFacilities() {
    var facilities = new List<Facility>(); 
    facilities = _facilityRepository.GetAll().ToList();
    var facReturnList = 
        facilities.Where(x => x.Fac_Name = "Something")
                  .OrderBy(x => x.Fac_Name).ToList();
    var facReturnList2 = 
        facReturnList.Select(x => 
            new { ID = x.Fac_Name.Substring(0, 6), 
                  Fac_Name = x.Fac_Name.Substring(0, 3) })
            .Distinct().ToList();
    return facReturnList2;
}

我试着在new之后添加List<Facility>,但它说这些属性(IDFac_Name)没有在Facility中定义。

在c#中使用LINQ . select时如何维护类型?

你想用你的结果初始化新的Facility实例吗?

var facReturnList2 = facReturnList.Select(x => new Facility { ID =   // ...
                                                   ^ concrete type initializer

对编辑的响应:在Select操作符中,需要指定要初始化的元素的类型,而不是它们的列表。您之前的代码似乎表明Fac_Name 是在Facility中定义的,但它显然不会在List<Facility>中定义。

您将获得匿名类型,因为您正在创建它。

.Select(x => new {

如果你不想那样做,就不要那样做。

如果一个现有的类型已经有了你需要的名称和精确的属性,就使用它。如果没有类型具有所需的内容,则创建一个。则可以返回该类型的适当列表或可枚举对象。

.Select(x => new YourDefinedType { 

听起来你真正想要的是一个DistinctBy方法。你想要指定一些方法来指示一个对象是不同的,但你不希望结果是那个选择的集合,你希望最终结果是开始对象。LINQ没有内置DistinctBy,但实现一个很容易:

public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer = null)
{
    comparer = comparer ?? EqualityComparer<TKey>.Default;
    HashSet<TKey> knownKeys = new HashSet<TKey>(comparer);
    foreach (TSource element in source)
    {
        if (knownKeys.Add(keySelector(element)))
        {
            yield return element;
        }
    }
}

使用它你的代码现在可以变成:

public List<Facility> GetFacilities()
{
    return _facilityRepository.GetAll()
        .Where(x => x.Fac_Name == "Something")
        .DistinctBy(x => new
        {
            ID = x.Fac_Name.Substring(0, 6),
            Fac_Name = x.Fac_Name.Substring(0, 3)
        })
        .OrderBy(x => x.Fac_Name)
        .ToList();
}

如果您有一个IQueryable而不是内存中的数据集,您可以使用GroupBy来获得相同的行为。在Linq-to-objects中,使用GroupBy的效率会低很多,但对于查询提供程序来说,它不会因为数据库能够优化而降低效率。

public List<Facility> GetFacilities()
{
    return _facilityRepository.GetAll()
        .Where(x => x.Fac_Name == "Something")
        .OrderBy(x => x.Fac_Name)
        .GroupBy(x => new
        {
            ID = x.Fac_Name.Substring(0, 6),
            Fac_Name = x.Fac_Name.Substring(0, 3)
        })
        .Select(group => group.First())
        .ToList();
}

下面的代码指示linq返回一个匿名类型:

.Select(x => new { ID = x.Fac_Name.Substring(0, 6), Fac_Name = x.Fac_Name.Substring(0, 3) }

你需要为你的结果创建一个类

public class Result{
    public string ID { get;set; }
    public string Fac_Name { get; set; }
}
//Then do
.Select(x => new Result { ID = x.Fac_Name.Substring(0, 6), Fac_Name = x.Fac_Name.Substring(0, 3) }

这确保您只返回您需要的信息