使用linq返回从列表<;t>;

本文关键字:lt gt 列表 linq 返回 使用 | 更新日期: 2023-09-27 18:26:34

我有以下代码:

public class UserList
    {
        public string UName { get; set; }
        public string Auth { get; set; }
        public Boolean PUser { get; set; }
    }

    class DeveloperPreview
    {
        List<UserList> UserList = new List<UserList>();
        public void PopulateUsers()
        {
            UserList.Add(new UserList() { UName="Daryl",Auth="12345",PUser=true});
            UserList.Add(new UserList() { UName = "Test", Auth = "239", PUser = false });
            UserList.Add(new UserList() { UName="Developer",Auth="2",PUser=true});
        }
        public string Authenticateuser(string Username, string Auth)
        {
            var User = UserList.Where((t => t.UName.Contains(Username)));
            return User.UName;
        }
    }

由调用

    DeveloperPreview Dev = new DeveloperPreview();
    private void SubmitClick(object sender, RoutedEventArgs e)
    {
        Dev.PopulateUsers();
        string Auth = Dev.Authenticateuser("Daryl","2");
        MessageBox.Show(Auth);
    }

我很难只返回列表中包含"Daryl"的行

我用这个作为参考:C#LINQ从列表中选择

但是我在如何实际执行这项任务方面仍然有一些困难,我后来希望操作/处理从列表中收集的数据,但这是另一个将在必要时构建的桥梁

使用linq返回从列表<;t>;

问题出现在以下几行:

 var User = UserList.Where((t => t.UName.Contains(Username)));
 return User.UName;

Enumerable.Where将返回一个IEnumerable<T>,它是记录的集合,而不是单个记录。因此,稍后当您尝试访问User.UName时,会出现错误。您需要选择一条记录。您可以根据需要使用First/FirstOrDefault/SingleOrDefault。你的方法可能是:

public string Authenticateuser(string Username, string Auth)
{
    var User = UserList.FirstOrDefault(t => t.UName.Contains(Username));
    if(User != null)    
       return User.UName;
    else  //user not found
       return null;//throw exception / Message etc
}

阅读:LINQ Single vs SingleOrDefault vs First vs FirstOrDefault

我想你真正需要做的就是改变这个:

var User = UserList.Where((t => t.UName.Contains(Username)));

到此:

var User = UserList.Where((t => t.UName.Contains(Username))).FirstOrDefault();

Where语句返回一个IEnumerable,您需要该IEnumeraable的第一个结果。

这:

var User = UserList.Where((t => t.UName.Contains(Username)));

返回一个IEnumerable<T>,而不是单个项目。你可能想要的是:

var User = UserList.Where((t => t.UName.Contains(Username))).FirstOrDefault();

这将返回第一个匹配项(如果未找到,则返回null)。

您可以使用:

var User = UserList.Where(t => t.UName == Username).FirstOrDefault();

我不知道这是否会引起问题,但让属性名与对象名匹配可能会让人很困惑。您正在使用"UserList"来表示UserList对象的列表。

我认为这会更有意义:

public class User
{
    public string UName { get; set; }
    public string Auth { get; set; }
    public Boolean PUser { get; set; }
}
class DeveloperPreview
{
    List<User> UserList = new List<User>();
    public void PopulateUsers()
    {
        UserList.Add(new User() { UName="Daryl",Auth="12345",PUser=true});
        UserList.Add(new User() { UName = "Test", Auth = "239", PUser = false });
        UserList.Add(new User() { UName="Developer",Auth="2",PUser=true});
    }
    public string Authenticateuser(string Username, string Auth)
    {
        var user = UserList.Where(t => t.UName == Username).FirstOrDefault();
        return user.UName;
    }
}

这里发生的事情就是这样。Where正在缩小列表的范围,但总是返回一个IEnumerable<>,即使那个可枚举对象只包含一个元素。如果您想返回一行,您需要添加对以下方法之一的调用

  • .First()返回第一个元素,如果没有第一个元素则返回错误
  • .FirstOrDefault()返回第一个元素,如果没有,则返回null
  • .Single()返回单个对象,如果没有一个对象则返回错误
  • .SingleOrDefault()返回单个对象,如果没有,则返回null,如果有多个,则返回error

请注意,除这些扩展方法外,所有扩展方法都返回IEnumerable,这样您就可以将调用链接到它们,例如

UserList
    .Where( t => t.UName.Contains(Username) )
    .Select( t => t.UName )
    .DefaultIfEmpty(string.Empty)
    .First();